在where子句中使用“caseexpression列”

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

这失败了:

ORA-00904:“%s:无效标识符”

有没有办法在Oracle 10.2 SQL中克服这个限制? 如何在where子句中使用“caseexpression列”?

这个错误的原因是SQL SELECT语句在逻辑上按以下顺序处理:

  • FROM :select一个或多个JOINed表和所有符合ON条件的行组合。

  • WHERE :条件被评估,不匹配的行被删除。

  • GROUP BY :行被分组(并且每个组都折叠成一行)

  • HAVING :评估条件,删除不匹配的行。

  • SELECT :评估列的列表。

  • DISTINCT :删除重复的行(如果它是一个SELECT DISTINCT语句)

  • UNIONEXCEPTINTERSECT :该操作数的操作取决于子SELECT语句的行。 例如,如果是UNION,则在评估所有子SELECT语句之后,将收集所有行(除非它是UNION ALL,否则将重复删除)。 因此对于EXCEPT或INTERSECT情况。

  • ORDER BY :行是有序的。

因此,您不能在WHERE子句中使用尚未填充或计算的东西。 另请参阅以下问题: oracle-sql-clause-evaluation-order

* 逻辑处理: 请注意,数据库引擎也可以为查询select另一个评估顺序(这就是他们通常所做的)。唯一的限制是结果应该与使用上述顺序相同


解决方法是将查询放在另一个查询中

 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' ; 

或者在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' ; 

我想这是你的查询的简化版本,或者你可以使用:

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

你的表不包含“department”列,因此你不能在where子句中引用它。 改用deptno。

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

这为我工作:

 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'; 

尝试:

  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'; 

在select之前,Oracle会尝试通过首先转到where子句来过滤要从表中扫描的logging数,这就是为什么查询失败的原因。 此外,您的查询将永远不会返回部门的行 – “帐户或未知”,因为filterDepartment =“SALES”

尝试下面的代码,这将很容易被引擎抓取:

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