Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Verwenden von „Case-Ausdrucksspalte“ in der Where-Klausel

Der Grund für diesen Fehler ist, dass SQL SELECT Aussagen sind logisch * in der folgenden Reihenfolge verarbeitet:

  • FROM :Auswahl einer Tabelle oder vieler JOINed-Tabellen und aller Zeilenkombinationen, die mit ON übereinstimmen Bedingungen.

  • WHERE :Bedingungen werden ausgewertet und Zeilen, die nicht übereinstimmen, werden entfernt.

  • GROUP BY :Zeilen werden gruppiert (und jede Gruppe reduziert sich auf eine Zeile)

  • HAVING :Bedingungen werden ausgewertet und Zeilen, die nicht übereinstimmen, werden entfernt.

  • SELECT :Spaltenliste wird ausgewertet.

  • DISTINCT :Doppelte Zeilen werden entfernt (wenn es sich um eine SELECT DISTINCT-Anweisung handelt)

  • UNION , EXCEPT , INTERSECT :Die Aktion dieses Operanden wird auf die Zeilen von Unter-SELECT-Anweisungen angewendet. Wenn es sich beispielsweise um eine UNION handelt, werden alle Zeilen gesammelt (und Duplikate werden eliminiert, es sei denn, es handelt sich um eine UNION ALL), nachdem alle untergeordneten SELECT-Anweisungen ausgewertet wurden. Entsprechend für die Fälle EXCEPT oder INTERSECT.

  • ORDER BY :Zeilen sind geordnet.

Daher können Sie in WHERE nicht verwenden -Klausel, etwas, das noch nicht ausgefüllt oder berechnet wurde. Siehe auch diese Frage:oracle-sql-clause-evaluation-order

Beachten Sie, dass Datenbank-Engines auch eine andere Auswertungsreihenfolge für eine Abfrage wählen können (und das tun sie normalerweise auch!). Die einzige Einschränkung besteht darin, dass die Ergebnisse die gleichen sein sollten, als ob die obige Reihenfolge verwendet würde .

Die Lösung besteht darin, die Abfrage in eine andere einzuschließen :

SELECT *
FROM
  ( SELECT ename
         , job
         , CASE deptno
             WHEN 10 THEN 'ACCOUNTS'
             WHEN 20 THEN 'SALES'
                     ELSE 'UNKNOWN'
           END AS department
    FROM emp
  ) tmp
WHERE department = 'SALES' ;

oder um die Berechnung in der WHERE-Bedingung zu duplizieren :

SELECT ename
     , job
     , CASE deptno
         WHEN 10 THEN 'ACCOUNTS'
         WHEN 20 THEN 'SALES'
                 ELSE 'UNKNOWN'
       END AS department
FROM emp
WHERE
    CASE deptno
      WHEN 10 THEN 'ACCOUNTS'
      WHEN 20 THEN 'SALES'
              ELSE 'UNKNOWN'
    END = 'SALES' ;

Ich denke, dies ist eine vereinfachte Version Ihrer Abfrage, oder Sie könnten Folgendes verwenden:

SELECT ename
     , job
     , 'SALES' AS department
FROM emp
WHERE deptno = 20 ;