SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */
WHERE department = 'SALES'
Das schlägt fehl:
ORA-00904: "% s: ungültige Kennung"
Gibt es eine Möglichkeit, diese Einschränkung in Oracle 10.2 SQL zu überwinden?.
Der Grund für diesen Fehler ist, dass SQL-Anweisungen SELECT
logisch * in der folgenden Reihenfolge verarbeitet werden:
FROM
: Auswahl einer oder mehrerer JOIN-Tabellen und aller Zeilenkombinationen, die den Bedingungen ON
entsprechen.
WHERE
: Bedingungen werden ausgewertet und nicht übereinstimmende Zeilen werden entfernt.
GROUP BY
: Zeilen werden gruppiert (und jede Gruppe wird zu einer Zeile zusammengefasst)
HAVING
: Bedingungen werden ausgewertet und nicht übereinstimmende Zeilen werden entfernt.
SELECT
: Liste der Spalten wird ausgewertet.
DISTINCT
: doppelte Zeilen werden entfernt (falls es sich um eine SELECT DISTINCT-Anweisung handelt)
UNION
, EXCEPT
, INTERSECT
: Die Aktion dieses Operanden wird für die Zeilen der untergeordneten SELECT-Anweisungen ausgeführt. Wenn es sich beispielsweise um eine UNION handelt, werden alle Zeilen erfasst (und Duplikate entfernt, sofern es sich nicht um eine UNION ALL handelt), nachdem alle untergeordneten SELECT-Anweisungen ausgewertet wurden. Entsprechend für die EXCEPT- oder INTERSECT-Fälle.
ORDER BY
: Zeilen werden sortiert.
Daher können Sie in der WHERE
-Klausel nichts verwenden, was noch nicht ausgefüllt oder berechnet wurde. Siehe auch diese Frage: Oracle-SQL-Klausel-Evaluierungsreihenfolge
* logisch verarbeitet: Beachten Sie, dass Datenbank-Engines auch eine andere Auswertungsreihenfolge für eine Abfrage wählen können (und das tun sie normalerweise!). Die einzige Einschränkung ist, dass die Ergebnisse die sein sollten das gleiche, als ob die obige Reihenfolge verwendet wurde .
Lösung ist , die Abfrage in eine andere einzufügen :
_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 ;
_
Ihre Tabelle enthält keine Spalte "Abteilung" und kann daher nicht in Ihrer where-Klausel referenziert werden. Verwenden Sie stattdessen deptno.
SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */ where deptno = 20;
Diese Arbeit für mich:
SELECT ename, job
FROM emp
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
WHEN deptno = 20 THEN 'SALES'
ELSE 'UNKNOWN'
END
= 'SALES'
select emp_.*
from (SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */ ) emp_ where emp_.department='UNKNOWN';
versuchen:
SQL> SELECT ename
2 , job
3 , CASE
4 WHEN deptno = 10
5 THEN 'ACCOUNTS'
6 WHEN deptno = 20
7 THEN 'SALES'
12 ELSE 'UNKNOWN'
13 END AS department
14 FROM emp /* !!! */ where department = 'SALES';
Oracle versucht, die Anzahl der zu durchsuchenden Datensätze aus der Tabelle zu filtern, indem Sie zuerst die where-Klausel auswählen, bevor Sie select auswählen. Deshalb schlägt Ihre Abfrage fehl. Darüber hinaus hätte Ihre Abfrage aufgrund des Filters Department = "SALES" niemals Zeilen mit der Abteilung "Konten oder Unbekannt" zurückgegeben.
Versuchen Sie es stattdessen unten, das kann einfach von Engine abgerufen werden:
SELECT ename, job, 'SALES' AS Abteilung FROM emp WHERE deptno = 20;