このエラーの理由は、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 ;