繁体   English   中英

在 where 子句中使用“案例表达式列”

[英]Using 'case expression column' in where clause

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 子句中使用“案例表达式列”?

出现这个错误的原因是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 :行是有序的。

因此,您不能在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' ;

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

您的表不包含“部门”列,因此您不能在 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';

Oracle 尝试通过在 select 之前先执行 where 子句来过滤要从表中扫描的记录数,这就是您的查询失败的原因。 此外,由于过滤器 Department="SALES",您的查询将永远不会返回带有部门的行 - “Accounts or Unknown”

请改用下面的方法,这将很容易被 Engine 获取:

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

尝试:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM