在where子句中使用'case expression column'

Eug*_*neP 24 sql oracle oracle10g ora-00904

SELECT ename
  ,    job
  ,    CASE deptno
         WHEN 10
           THEN 'ACCOUNTS'
         WHEN 20
           THEN 'SALES'
         ELSE 'UNKNOWN'
       END AS department
FROM emp /* !!! */ 
WHERE department = 'SALES'
Run Code Online (Sandbox Code Playgroud)

这失败了:

ORA-00904:"%s:无效标识符"

有没有办法克服Oracle 10.2 SQL中的这种限制?如何在where子句中使用'case expression column'?

ype*_*eᵀᴹ 42

出现此错误的原因是SQL SELECT语句按以下顺序进行逻辑*处理:

  • FROM:选择一个表或多个JOINed以及符合ON条件的所有行组合.

  • WHERE:评估条件,并删除不匹配的行.

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

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

  • SELECT:评估列的列表.

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

  • UNION,EXCEPT,INTERSECT:那个操作的动作是在子SELECT语句的行拍摄.例如,如果它是UNION,则在评估所有子SELECT语句之后,将收集所有行(并删除重复项,除非它是UNION ALL).因此对于EXCEPT或INTERSECT案件.

  • ORDER BY:行是有序的.

因此,您不能使用in WHERE子句,即尚未填充或计算的内容.另见这个问题:oracle-sql-clause-evaluation-order

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


解决方案是将查询包含在另一个中:

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' ;
Run Code Online (Sandbox Code Playgroud)

或者在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' ;
Run Code Online (Sandbox Code Playgroud)

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

SELECT ename
     , job
     , 'SALES' AS department
FROM emp
WHERE deptno = 20 ;
Run Code Online (Sandbox Code Playgroud)


Mar*_*onk 7

您的表不包含列"部门",因此您无法在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;
Run Code Online (Sandbox Code Playgroud)


Cyr*_*don 5

这对我有用:

SELECT ename, job
FROM   emp 
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
           WHEN deptno = 20 THEN 'SALES'
           ELSE 'UNKNOWN'  
      END
      = 'SALES'
Run Code Online (Sandbox Code Playgroud)