Wie verwende ich CASE..WHEN in MySQL richtig?

71

Hier ist eine Demo-Abfrage. Beachten Sie, dass sie sehr einfach ist. Ruft nur ab, wenn base_price 0 ist. Und wählt dennoch die Bedingung 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 ist decimal(8,0)

Wenn ich dies auf meiner Datenbank ausführe, erhalte ich:

3 0
3 0
3 0
3 0
3 0

Itay Moav-Malimovka
quelle

Antworten:

70

Entfernen Sie die course_enrollment_settings.base_priceunmittelbar danach CASE:

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

CASEhat zwei verschiedene Formen, wie im Handbuch beschrieben . Hier sollten Sie die zweite Form , da Sie mit Suchbedingungen .

NPE
quelle
Wenn Sie nach den Werten sortieren möchten, wie würde die Reihenfolge nach Klausel aussehen, da es keinen Spaltenalias gibt?
HPWD
38
CASE case_value
    WHEN when_value THEN statements
    [WHEN when_value THEN statements]
    ELSE statements
END 

Oder:

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

Hier ist CASE ein Ausdruck im 2. Szenario. search_condition wird ausgewertet. Wenn keine search_condition gleich ist, führen Sie else aus

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

sollte sein

SELECT
   CASE 
    WHEN course_enrollment_settings.base_price = 0      THEN 1
kapil das
quelle
Was sind die Klammern? [und]
Shafizadeh
@Shafizadeh diese implizieren, dass Sie mehr als Anweisungen nach dem ersten hinzufügen könnten.
Douwe de Haan
14

CASE course_enrollment_settings.base_price ist hier falsch, es sollte gerecht sein 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 

Einige Erklärungen. Ihre ursprüngliche Abfrage wird ausgeführt als:

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

deshalb bekommst du immer 3

a1ex07
quelle
1
"Keine Notwendigkeit für" ist ungenau. Es ist "du solltest nicht haben".
Leichtigkeitsrennen im Orbit
@ Lightness Races in Orbi: zustimmen; Ich habe es geändert und einige Erklärungen hinzugefügt
a1ex07
Beim Hinzufügen eines Spaltenalias wurde eine Fehlermeldung angezeigt AS 'calc_base_price. Ich löste es, indem ich Klammern um das Ganze hinzufügte(CASE ... END)
pgr
6
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
Teja
quelle
Die Bedingungen wurden ein wenig geändert. <= 100 statt <101 hinzugefügt
Teja
5

Es gibt zwei Varianten vonCASE , und Sie verwenden nicht die, von der Sie glauben, dass Sie sie sind.

Was tust du

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

Jede Bedingung entspricht lose einem if (case_value == when_value)(Pseudocode).

Sie haben jedoch eine ganze Bedingung als gesetzt when_value, was zu etwas führt wie:

if (case_value == (case_value > 100))

Jetzt (case_value > 100)bewertet FALSEund ist die einzige Ihrer Bedingungen, um dies zu tun. Jetzt haben Sie also:

if (case_value == FALSE)

FALSEKonvertiert in 0und durch den resultierenden vollständigen Ausdruck können if (case_value == 0)Sie jetzt sehen, warum die dritte Bedingung ausgelöst wird.

Was sollst du tun?

Löschen Sie die erste, course_enrollment_settingsdamit es keine gibt case_value, sodass MySQL weiß, dass Sie die zweite Variante von verwenden möchten CASE:

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

Jetzt können Sie Ihre vollständigen Bedingungen als bereitstellen search_condition.

Lesen Sie auch die Dokumentation zu den von Ihnen verwendeten Funktionen.

Leichtigkeitsrennen im Orbit
quelle
1
Was ich brauchte - das war klar genug, dass ich es tatsächlich an meine Situation anpassen konnte.
Betty Mock
1

Ich denke, ein Teil davon ist, dass Sie den Wert angeben, nach dem Sie auswählen CASE, und anschließend die WHEN x = ySyntax verwenden, die eine Kombination aus zwei verschiedenen Verwendungsmethoden darstellt CASE. Es sollte entweder sein

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

oder

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