使用“case 表达式列”;在 where 子句中

发布于 2024-11-18 04:18:15 字数 388 浏览 6 评论 0原文

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

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

This fails:

ORA-00904: "%s: invalid identifier"

Is there a way to overcome this limitation in Oracle 10.2 SQL ?
How to use the 'case expression column' in where clause ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蝶…霜飞 2024-11-25 04:18:15

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

  • FROM:选择一个表或多个 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 *
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 ;

The reason for this error is that SQL SELECT statements are logically * processed in the following order:

  • FROM: selection of one table or many JOINed ones and all rows combinations that match the ON conditions.

  • WHERE: conditions are evaluated and rows that do not match are removed.

  • GROUP BY: rows are grouped (and every group collapses to one row)

  • HAVING: conditions are evaluated and rows that do not match are removed.

  • SELECT: list of columns is evaluated.

  • DISTINCT: duplicate rows are removed (if it's a SELECT DISTINCT statement)

  • UNION, EXCEPT, INTERSECT: the action of that operand is taken upon the rows of sub-SELECT statements. For example, if it's a UNION, all rows are gathered (and duplicates eliminated unless it's a UNION ALL) after all sub-SELECT statements are evaluated. Accordingly for the EXCEPT or INTERSECT cases.

  • ORDER BY: rows are ordered.

Therefore, you can't use in WHERE clause, something that hasn't been populated or calculated yet. See also this question: oracle-sql-clause-evaluation-order

* logically processed: Note that database engines may as well choose another order of evaluation for a query (and that's what they usually do!) The only restriction is that the results should be the same as if the above order was used.


Solution is to enclose the query in another one:

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

or to duplicate the calculation in the WHERE condition:

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

I guess this is a simplified version of your query or you could use:

SELECT ename
     , job
     , 'SALES' AS department
FROM emp
WHERE deptno = 20 ;
何必那么矫情 2024-11-25 04:18:15

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

Your table does not contain a column "department" and thus you can not reference it in your where clause. Use deptno instead.

SELECT ename
,      job
,      CASE deptno
          WHEN 10
          THEN 'ACCOUNTS'
          WHEN 20
          THEN 'SALES'
          ELSE 'UNKNOWN'
       END AS department
FROM   emp /* !!! */ where deptno = 20;
空城仅有旧梦在 2024-11-25 04:18:15

这对我有用:

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

This work for me :

SELECT ename, job
FROM   emp 
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
           WHEN deptno = 20 THEN 'SALES'
           ELSE 'UNKNOWN'  
      END
      = 'SALES'
软甜啾 2024-11-25 04:18:15
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';
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';
稀香 2024-11-25 04:18:15

尝试:

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

try:

  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';
世界等同你 2024-11-25 04:18:15

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

请尝试下面的操作,这将很容易被引擎获取:

SELECT ename, job,'SALES' AS Department
来自员工
其中部门编号 = 20;

Oracle tries to filter the number of records to be scanned from table by going for the where clause first before select that is why your query fails. Moreover, your query would have never returned rows with department - "Accounts or Unknown" because of the filter Department="SALES"

Try below instead, that will be easy to be fetched by Engine :

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文