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

4

6 に答える 6

55

このエラーの理由は、SQLSELECTステートメントが次の順序で論理的に*処理されるためです。

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

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

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

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

  • SELECT: 列のリストが評価されます。

  • DISTINCT: 重複する行は削除されます (SELECT DISTINCT ステートメントの場合)

  • UNION, EXCEPT, INTERSECT: そのオペランドのアクションは、サブ SELECT ステートメントの行に対して実行されます。たとえば、UNION の場合、すべてのサブ SELECT ステートメントが評価された後に、すべての行が収集されます (UNION ALL でない限り、重複は排除されます)。したがって、EXCEPT または INTERSECT の場合も同様です。

  • ORDER BY: 行は順序付けされています。

したがって、WHEREまだ入力も計算もされていない in 句を使用することはできません。この質問も参照してください: 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 ;
于 2011-07-01T08:53:54.223 に答える
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;
于 2011-07-01T08:59:24.213 に答える
5

これは私にとってはうまくいきます:

SELECT ename, job
FROM   emp 
WHERE CASE WHEN deptno = 10 THEN 'ACCOUNTS'
           WHEN deptno = 20 THEN 'SALES'
           ELSE 'UNKNOWN'  
      END
      = 'SALES'
于 2011-07-01T09:01:22.697 に答える
0

Oracle は、select の前にまず where 句を使用して、テーブルからスキャンするレコードの数をフィルタリングしようとします。これが、クエリが失敗する理由です。さらに、フィルター Department="SALES" のため、クエリは部門 - "Accounts or Unknown" を含む行を返すことはありませんでした。

代わりに以下を試してください。これは Engine によって簡単にフェッチされます。

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

于 2016-01-14T13:38:57.643 に答える
0

試す:

  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';
于 2011-07-01T08:55:30.287 に答える