Cómo uso correctamente el CASO..CUANDO en MySQL


Aquí hay una consulta de demostración, observe que es muy simple, obtiene solo donde base_price es 0, Y aún así, elige la condición 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 es decimal(8,0)

Cuando se ejecuta esto en mi DB, obtengo:

3 0
3 0
3 0
3 0
3 0

Author: Itay Moav -Malimovka, 2012-03-06

6 answers

Eliminar el course_enrollment_settings.base_price inmediatamente después de CASE:

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

CASE tiene dos formas diferentes, como se detalla en el manual . Aquí, quieres el segundo formulario ya que estás usando condiciones de búsqueda.

 38
Author: NPE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 11:31:30
CASE case_value
    WHEN when_value THEN statements
    [WHEN when_value THEN statements]
    ELSE statements
END 

O:

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

Aquí CASE es una expresión en el segundo escenario search_condition evaluará y si no search_condition es igual entonces ejecutar else

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

Debe ser

SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1
 27
Author: kapil das,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-17 06:16:25

CASE course_enrollment_settings.base_price está mal aquí, debe ser solo 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 

Algunas explicaciones. Su consulta original se ejecutará como:

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, ...

Es por eso que siempre obtienes 3

 10
Author: a1ex07,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 16:54:35
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
 5
Author: Teja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 16:46:28

Hay dos variantes de CASE, y no estás usando el que crees que eres.

Lo que estás haciendo

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

Cada condición es vagamente equivalente a un if (case_value == when_value) (pseudo-código).

Sin embargo, has puesto una condición completa como when_value, lo que lleva a algo como:

if (case_value == (case_value > 100))

Ahora, (case_value > 100) evalúa a FALSE, y es la única de sus condiciones para hacerlo. Entonces, ahora tienes:

if (case_value == FALSE)

FALSE se convierte a 0 y, a través de la la expresión completa resultante if (case_value == 0) ahora puede ver por qué se dispara la tercera condición.

Lo que se supone que debes hacer

Suelta la primera course_enrollment_settings para que no haya case_value, haciendo que MySQL sepa que tienes la intención de usar la segunda variante de CASE:

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

Ahora puedes proporcionar tus condicionales completos como search_condition.

Además, lea la documentación de las funciones que utiliza.

 5
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 16:50:07

Creo que parte de esto es que estás indicando el valor que estás seleccionando después de CASE, y luego usando la sintaxis WHEN x = y después, que es una combinación de dos métodos diferentes de usar CASE. Debe ser

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

O

CASE
  WHEN x = a THEN ...
  WHEN x = b THEN ...
 1
Author: Kaji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-06 16:51:18