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
ステートメントがlogically*で処理されるためです次の順序:
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
句では使用できません。これは、まだ設定または計算されていないものです。この質問も参照してください: 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 ;
テーブルには列「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;
私のためのこの仕事:
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';
試してください:
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';
Oracleは、selectの前に最初にwhere句を検索することで、テーブルからスキャンするレコードの数をフィルター処理しようとするため、クエリが失敗します。さらに、クエリは、部門「SALES」のために部門-「アカウントまたは不明」の行を決して返しませんでした。
代わりに以下を試してください。Engineで簡単に取得できます:
SELECT ename、job、 'SALES' AS department FROM emp WHERE deptno = 20;