2015-10-07 90 views
2

數據庫使用SQL * Plus 11.2在Oracle Database 11g上運行。在WITH子句中不允許使用聚合方法,或者使用WITH做一些神奇的事情?此代碼告訴我「most_expensive」是一個無效的標識符。然而,子查詢沒有問題。Oracle SQL Plus WITH子句「無效標識符」

WITH most_expensive AS (SELECT MAX (enrollment_cost) FROM Enrollments) 
SELECT e.member_id 
FROM Enrollments e 
WHERE e.enrollment_cost = most_expensive; 
+1

您的查詢中沒有_column_ name'most_expensive' - 只有一個子查詢。但是你在你的'where'子句中提到了這個名字的列 –

回答

3

查詢因子分解(使用子句)允許您定義臨時表別名。 在您的示例中,most_expensive將引用包含具有單列的單個行的表對象。您可以在查詢的任何地方使用它,您可以使用表格。 現在,如果您創建一個名爲t1的表(使用create table statment),給它一列並插入1行,您仍然無法執行「WHERE x = t1」。
換句話說,子查詢並不總是與表相同,WITH子句爲您提供的行爲與表格不同,不像子查詢。

下工作,但:

WITH most_expensive AS (SELECT MAX (enrollment_cost) FROM Enrollments) 
SELECT member_id 
FROM Enrollments e 
WHERE e.enrollment_cost = (select * from most_expensive); 

http://sqlfiddle.com/#!4/9eecb7/6340

+0

謝謝,你的回答很有幫助。但是,什麼是子查詢返回呢?我認爲它也只是回饋1行和1的表。它仍然有助於大型查詢,但我希望有一種方法來保持一個臨時變量,以保持實際查詢更清潔一點(對此並不多SQL代碼片段,但未來)。 – Watercycle

+0

不幸的是,SQL有很多像這樣愚蠢的非直觀角落。從技術上講,子查詢也不應該起作用 - 子查詢的結果是元組的集合,而不是單個數字,但支持col =(子查詢)非常方便,我猜他們無法拒絕爲此添加支持。對錶格做同樣的事情會很糟糕 - 至少在查看子查詢時,你可以說「是的,這將返回一個單一的數字」。沒有辦法強制一個表總是單列單行。除了你有子查詢因子。但是那太過分了。 –

+0

在添加subquerying之前加入子查詢的唯一替代方法嗎?他們現在似乎是標準的一部分。 – Watercycle

1

我沒有看到使用子查詢融通(WITH子句)在這裏的任何好處。查詢可以簡單地寫爲:

SELECT member_id 
FROM Enrollments e 
WHERE e.enrollment_cost = 
    (SELECT MAX (enrollment_cost) FROM Enrollments 
); 

比較解釋計劃:

無子查詢保:

SQL> set autot on explain 
SQL> SELECT empno FROM emp e WHERE e.sal = 
    2 (SELECT MAX (sal) FROM emp 
    3 ); 

    EMPNO 
---------- 
     7839 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1876299339 

---------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
---------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  8 |  8 (0)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL | EMP |  1 |  8 |  4 (0)| 00:00:01 | 
| 2 | SORT AGGREGATE |  |  1 |  4 |   |   | 
| 3 | TABLE ACCESS FULL| EMP | 14 | 56 |  4 (0)| 00:00:01 | 
---------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("E"."SAL"= (SELECT MAX("SAL") FROM "EMP" "EMP")) 

隨着子查詢的保理:

SQL> WITH max_sal AS 
    2 (SELECT MAX (sal) sal FROM emp 
    3 ) 
    4 SELECT empno FROM emp e WHERE e.sal = 
    5 (SELECT sal FROM max_sal 
    6 ); 

    EMPNO 
---------- 
     7839 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 73843676 

----------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT  |  |  1 |  8 |  8 (0)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL | EMP |  1 |  8 |  4 (0)| 00:00:01 | 
| 2 | VIEW    |  |  1 | 13 |  4 (0)| 00:00:01 | 
| 3 | SORT AGGREGATE |  |  1 |  4 |   |   | 
| 4 |  TABLE ACCESS FULL| EMP | 14 | 56 |  4 (0)| 00:00:01 | 
----------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("E"."SAL"= (SELECT "SAL" FROM (SELECT MAX("SAL") "SAL" 
       FROM "EMP" "EMP") "MAX_SAL")) 

請參閱應用的過濾器,您所做的只是將其嵌套查詢並深入一層,而不實際添加任何好處。

+1

希望子查詢保理能夠通過從主查詢中獲取絨毛使代碼更具可讀性。我想我希望爲查詢的本地變量。 – Watercycle

0

您的因式分解查詢(表格)被命名爲most_expensive,但您將其用作列名稱。在這種情況下,您應該使用keep first

SELECT max(member_id) KEEP (DENSE_RANK FIRST ORDER BY enrollment_cost desc nulls last) "Best" 
FROM Enrollments e 
WHERE e.enrollment_cost = most_expensive;