SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */
WHERE department = 'SALES'
Cela échoue:
ORA-00904: "% s: identificateur non valide"
Existe-t-il un moyen de surmonter cette limitation dans Oracle 10.2 SQL? Comment utiliser la 'colonne d'expression de cas' dans la clause where?
La raison de cette erreur est que les instructions SQL SELECT
sont logiquement * traitées dans l'ordre suivant:
FROM
: sélection d'une table ou de plusieurs tables JOINNELLES et de toutes les combinaisons de lignes correspondant aux conditions ON
.
WHERE
: les conditions sont évaluées et les lignes qui ne correspondent pas sont supprimées.
GROUP BY
: les lignes sont groupées (et chaque groupe se réduit à une ligne)
HAVING
: les conditions sont évaluées et les lignes qui ne correspondent pas sont supprimées.
SELECT
: la liste des colonnes est évaluée.
DISTINCT
: les lignes en double sont supprimées (s'il s'agit d'une instruction SELECT DISTINCT)
(UNION
, EXCEPT
, INTERSECT
: l'action de cet opérande est exécutée sur les lignes des instructions sous-SELECT. Par exemple, s'il s'agit d'un UNION, toutes les lignes sont rassemblées (et les doublons éliminés, sauf s'il s'agit d'un UNION ALL) une fois que toutes les instructions sous-SELECT ont été évaluées. En conséquence pour les cas EXCEPT ou INTERSECT.
ORDER BY
: les lignes sont ordonnées.
Par conséquent, vous ne pouvez pas utiliser dans la clause WHERE
, quelque chose qui n'a pas encore été rempli ou calculé. Voir aussi cette question: Oracle-sql-clause-evaluation-order
* logiquement traité: Notez que les moteurs de base de données peuvent également choisir un autre ordre d'évaluation pour une requête (et c'est ce qu'ils font habituellement!). La seule restriction est que le les résultats doivent être les mêmes que si l'ordre précédent était utilisé .
La solution est de inclure la requête dans une autre:
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' ;
ou to dupliquer le calcul dans la condition WHERE:
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' ;
Je suppose que ceci est une version simplifiée de votre requête ou vous pourriez utiliser:
SELECT ename
, job
, 'SALES' AS department
FROM emp
WHERE deptno = 20 ;
Votre table ne contient pas de colonne "department" et vous ne pouvez donc pas la référencer dans votre clause where. Utilisez deptno à la place.
SELECT ename
, job
, CASE deptno
WHEN 10
THEN 'ACCOUNTS'
WHEN 20
THEN 'SALES'
ELSE 'UNKNOWN'
END AS department
FROM emp /* !!! */ where deptno = 20;
Ce travail pour moi:
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';
essayer:
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 essaie de filtrer le nombre d'enregistrements à analyser à partir d'une table en recherchant d'abord la clause where avant de sélectionner, raison pour laquelle votre requête échoue. De plus, votre requête n'aurait jamais renvoyé de lignes avec le service - "Comptes ou Inconnu" en raison du filtre Department = "VENTES".
Essayez ci-dessous, cela sera facile à récupérer par le moteur:
SELECT ename, job, 'VENTES' AS département DE emp WHERE deptno = 20;