web-dev-qa-db-ja.com

where句で「case expression column」を使用する

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句で「ケース式列」を使用する方法は?

23
EugeneP

このエラーの理由は、SQL SELECTステートメントがlogically*で処理されるためです次の順序:

  • FROM:1つのテーブルまたは多数のJOINされたテーブルの選択と、ON条件に一致するすべての行の組み合わせ。

  • WHERE:条件が評価され、一致しない行が削除されます。

  • GROUP BY:行はグループ化されます(すべてのグループが1行に折りたたまれます)

  • 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 ;
41
ypercubeᵀᴹ

テーブルには列「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;
7

私のためのこの仕事:

SELECT ename, job
FROM   emp 
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
           WHEN deptno = 20 THEN 'SALES'
           ELSE 'UNKNOWN'  
      END
      = 'SALES'
4
Cyril Gandon
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';
1
Amitābha

試してください:

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

Oracleは、selectの前に最初にwhere句を検索することで、テーブルからスキャンするレコードの数をフィルター処理しようとするため、クエリが失敗します。さらに、クエリは、部門「SALES」のために部門-「アカウントまたは不明」の行を決して返しませんでした。

代わりに以下を試してください。Engineで簡単に取得できます:

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

0
Himansh Gautam