Как правильно использовать CASE..WHEN в MySQL - PullRequest
52 голосов
/ 06 марта 2012

Вот демонстрационный запрос, обратите внимание, что он очень прост, выбирает только там, где base_price равен 0, И все же, он выбирает условие 3:

SELECT
   CASE course_enrollment_settings.base_price
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    WHEN course_enrollment_settings.base_price<101      THEN 2
    WHEN course_enrollment_settings.base_price>100 AND   
                      course_enrollment_settings.base_price<201 THEN 3
        ELSE 6
   END AS 'calc_base_price',
   course_enrollment_settings.base_price
FROM
    course_enrollment_settings
WHERE course_enrollment_settings.base_price = 0

base_price равно decimal(8,0)

При запуске этого в моей БД я получаю:

3 0
3 0
3 0
3 0
3 0

Ответы [ 6 ]

52 голосов
/ 06 марта 2012

Снимите course_enrollment_settings.base_price сразу после CASE:

SELECT
   CASE
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    ...
    END

CASE имеет две различные формы, как описано в руководстве .Здесь вам нужна вторая форма, так как вы используете условия поиска .

32 голосов
/ 17 июля 2013
CASE case_value
    WHEN when_value THEN statements
    [WHEN when_value THEN statements]
    ELSE statements
END 

Или:

CASE
WHEN <search_condition> THEN statements
[WHEN <search_condition> THEN statements] 
ELSE statements
END 

здесь CASE - это выражение во 2-м сценарии, в котором search_condition будет оцениваться, и если никакое условие search_condition не равно, тогда выполнить иначе

SELECT
   CASE course_enrollment_settings.base_price
    WHEN course_enrollment_settings.base_price = 0      THEN 1

должно быть

SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1
11 голосов
/ 06 марта 2012

CASE course_enrollment_settings.base_price здесь не так, должно быть просто CASE

SELECT 
CASE 
WHEN course_enrollment_settings.base_price = 0      THEN 1 
WHEN course_enrollment_settings.base_price<101      THEN 2 
WHEN course_enrollment_settings.base_price>100 AND    
                  course_enrollment_settings.base_price<201 THEN 3 
    ELSE 6 
END AS 'calc_base_price', 
course_enrollment_settings.base_price 
FROM 
  course_enrollment_settings 
WHERE course_enrollment_settings.base_price = 0 

Некоторые пояснения.Ваш оригинальный запрос будет выполнен как:

SELECT 
CASE 0
WHEN 0=0 THEN 1 -- condition evaluates to 1, then 0 (from CASE 0)compares to 1 - false
WHEN 0<1 THEN 2 -- condition evaluates to 1,then 0 (from CASE 0)compares to 1 - false
WHEN 0>100 and 0<201 THEN 3 -- evaluates to 0 ,then 0 (from CASE 0)compares to 0 - true
ELSE 6, ...

, поэтому вы всегда получаете 3

5 голосов
/ 06 марта 2012

Есть два варианта CASE, и вы не используете тот, который вам кажется.

Что вы делаете

CASE case_value
    WHEN when_value THEN statement_list
    [WHEN when_value THEN statement_list] ...
    [ELSE statement_list]
END CASE

Каждое условие в некоторой степени эквивалентно if (case_value == when_value) (псевдокоду).

Однако вы задали целое условие как when_value, что приведет к чему-то вроде:

if (case_value == (case_value > 100))

Теперь (case_value > 100) оценивается как FALSE и является единственным из ваших условий, чтобы сделать это.Итак, теперь у вас есть:

if (case_value == FALSE)

FALSE преобразуется в 0 и, благодаря полученному полному выражению if (case_value == 0) теперь вы можете увидеть, почему срабатывает третье условие.

Чтовы должны сделать

Отбросить первый course_enrollment_settings, чтобы не было case_value, в результате чего MySQL узнает, что вы собираетесь использовать второй вариант CASE:

CASE
    WHEN search_condition THEN statement_list
    [WHEN search_condition THEN statement_list] ...
    [ELSE statement_list]
END CASE

Теперь вы можете предоставить полные условия в виде search_condition.

Кроме того, ознакомьтесь с документацией по используемым функциям.

5 голосов
/ 06 марта 2012
SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1
    WHEN course_enrollment_settings.base_price>0 AND  
         course_enrollment_settings.base_price<=100     THEN 2
    WHEN course_enrollment_settings.base_price>100 AND   
         course_enrollment_settings.base_price<201      THEN 3
        ELSE 6
   END AS 'calc_base_price',
   course_enrollment_settings.base_price
FROM
    course_enrollment_settings
WHERE course_enrollment_settings.base_price = 0
1 голос
/ 06 марта 2012

Я думаю, что отчасти это то, что вы указываете значение, которое выбираете после CASE, а затем используете синтаксис WHEN x = y, который представляет собой комбинацию двух разных методов использования CASE. Это должно быть либо

CASE X
  WHEN a THEN ...
  WHEN b THEN ...

или

CASE
  WHEN x = a THEN ...
  WHEN x = b THEN ...
...