web-dev-qa-db-ja.com

SQLがwhere句の列エイリアスを認識しない

私はSQLの初心者ですが、この厄介なエラーに遭遇しました。 SQLはこのスクリプトのWHERE句に問題があります:

SELECT
  ITEM_ID, ITEM_PRICE, DISCOUNT_AMOUNT, QUANTITY, 
  (ITEM_PRICE*QUANTITY) AS price_total, 
  (DISCOUNT_AMOUNT*QUANTITY) AS discount_total, 
  ((ITEM_PRICE-DISCOUNT_AMOUNT)*QUANTITY) AS item_total
FROM ORDER_ITEMS
WHERE item_total > 500
ORDER BY item_total;

このエラーが発生しました:

Error starting at line : 1 in command -
SELECT 
  ITEM_ID, ITEM_PRICE, DISCOUNT_AMOUNT, QUANTITY,  
  (ITEM_PRICE*QUANTITY) AS price_total,  
  (DISCOUNT_AMOUNT*QUANTITY) AS discount_total,  
  ((ITEM_PRICE-DISCOUNT_AMOUNT)*QUANTITY) AS item_total 
FROM ORDER_ITEMS 
WHERE item_total > 500 
ORDER BY item_total DESC;
Error at Command Line : 7 Column : 7
Error report -
SQL Error: ORA-00904: "ITEM_TOTAL": invalid identifier
00904. 00000 -  "%s: invalid identifier"
*Cause:    
*Action:

Price_totalにもdiscount_totalにも問題がない理由はわかりませんが、item_totalが無効であると報告されています。まず、割引額を差し引いて数量を掛けたときに、合計が500を超えるアイテムのみを選択しようとしています。次に、結果をitem_totalの降順で並べ替える必要があります

9
Somus

クエリ選択リストでエイリアスを使用して列に別の名前を付けることができます。GROUPBY、ORDER BY、またはHAVING句でエイリアスを使用して列を参照できます。

標準SQLでは、WHERE句の列エイリアスへの参照は許可されていません。WHERE句が評価されたときに、列の値がまだ決定されていない可能性があるため、この制限が課せられます。

したがって、次のクエリは不正です。

SQL> SELECT empno AS employee, deptno AS department, sal AS salary
  2  FROM emp
  3  WHERE employee = 7369;
WHERE employee = 7369
      *
ERROR at line 3:
ORA-00904: "EMPLOYEE": invalid identifier


SQL>

列エイリアスは次の場所で許可されています:

  • GROUP BY
  • ORDER BY
  • [〜#〜]持っている[〜#〜]

次の場合は、WHERE句で列エイリアスを参照できます。

  1. サブクエリ
  2. 共通テーブル式(CTE)

例えば、

SQL> SELECT * FROM
  2  (
  3  SELECT empno AS employee, deptno AS department, sal AS salary
  4  FROM emp
  5  )
  6  WHERE employee = 7369;

  EMPLOYEE DEPARTMENT     SALARY
---------- ---------- ----------
      7369         20        800

SQL> WITH DATA AS(
  2  SELECT empno AS employee, deptno AS department, sal AS salary
  3  FROM emp
  4  )
  5  SELECT * FROM DATA
  6  WHERE employee = 7369;

  EMPLOYEE DEPARTMENT     SALARY
---------- ---------- ----------
      7369         20        800

SQL>
17
Lalit Kumar B

クエリでエイリアスとして使用されている列名は使用できません

理由:

クエリは最初にランタイムをチェックします。このとき、列名「item_total」はテーブル「ORDER_ITEMS」に見つかりません。エイリアスとして指定されているため、どこにも保存されておらず、目的の出力のみにその列を割り当てています。

代わりの:

そのタイプを使用したい場合はサブクエリを使用してください。パフォーマンスは良くありませんが、これは代替方法の1つです

SELECT * FROM
 (SELECT
  ITEM_ID, ITEM_PRICE, DISCOUNT_AMOUNT, QUANTITY, 
  (ITEM_PRICE*QUANTITY) AS price_total, 
  (DISCOUNT_AMOUNT*QUANTITY) AS discount_total, 
  ((ITEM_PRICE-DISCOUNT_AMOUNT)*QUANTITY) AS item_total
 FROM ORDER_ITEMS) as  tbl
WHERE tbl.item_total > 500
ORDER BY tbl.item_total;
2

Oracle 12c以降では、CROSS APPLYを使用して式を定義し、WHERE句でそれらを参照できます。

SELECT
  o.ITEM_ID, o.ITEM_PRICE, o.DISCOUNT_AMOUNT, o.QUANTITY, 
  s.price_total, s.discount_total, s.item_total
FROM ORDER_ITEMS o
CROSS APPLY (SELECT ITEM_PRICE*QUANTITY AS price_total, 
                    DISCOUNT_AMOUNT*QUANTITY AS discount_total, 
                  (ITEM_PRICE-DISCOUNT_AMOUNT)*QUANTITY AS item_total FROM dual) s
WHERE s.item_total > 500
ORDER BY s.item_total;
0
Lukasz Szozda