我寫了這個查詢
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
FROM employees
WHERE SALARY > (SELECT AVG(SALARY)
FROM employees)
我有點困惑為什么我必須為它創建一個子查詢,為什么我不能像這樣撰寫查詢:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
FROM employees
WHERE SALARY > AVG(SALARY)
uj5u.com熱心網友回復:
SQL 是一種基于集合的語言。如果只聚合集合中的一列,則必須聚合整個集合。您不能既聚合集合又不聚合集合。此外,一個SELECT陳述句只定義一個集合。因此,您不能在同一個 SELECT 陳述句中將來自聚合集的值與來自非聚合集(兩個集)的值進行比較。
您的第一個陳述句有效,因為您有兩個 SELECT 陳述句,每個陳述句定義一個不同的集合。一組通過avg()函式聚合,另一組保持非聚合。
它也可以作業,因為聚合集是標量的(它有一個值)。它可以將非聚合集中的每一行與單值聚合集中保存的標量值進行比較。如果該聚合集以非標量的方式定義,則會引發錯誤,您將不得不通過ON子句JOIN內部的FROM子句或相關子查詢來建立兩個集之間的關系.
另一個原因是操作順序。通過WHERE子句進行過濾首先發生在 SQL 的執行中。在您的資料被過濾時,還沒有其他操作發生。GROUP BY/Aggregation 發生在 SQL 執行的后期。因此,您試圖將 SQL 中兩個非常不同的步驟的結果相互比較。
運算順序是存在的原因HAVING。它與聚合非常相似,WHERE但在聚合之后起作用。但是,這對您在此 SQL 中嘗試執行的操作無濟于事,因為您再次嘗試將非聚合集的值與聚合集的值進行比較,而這根本無法完成一個 SELECT 陳述句。
可能值得注意的是,您可以使用大多數 RDBMS 支持的“視窗函式”(也稱為“有序分析函式”或“分析函式”)在非聚合集內聚合(可以這么說)。
例如:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, AVG(SALARY) OVER () as avg_salary
FROM employees;
這仍然會為 t??able 中的每一行吐出一個非聚合行employees。它將有第 4 列,其中包含每一行所有員工的平均工資。每一行都將包含相同的值。
------------- ------------ ------------ -------- ------------
| EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | avg_salary |
------------- ------------ ------------ -------- ------------
| 1 | bob | mcbob | 100 | 210 |
| 2 | sue | o'susan | 230 | 210 |
| 3 | venkat | van venkat | 300 | 210 |
------------- ------------ ------------ -------- ------------
話雖如此,由于操作的順序,您無法比較 aWHERE或子句內的視窗函式的結果。HAVING視窗函式邏輯幾乎在 sql 執行的所有其他步驟之后運行。你只會得到一個不允許的錯誤。因此,您將再次需要兩個 SELECT 陳述句:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
FROM
(
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, AVG(SALARY) OVER () as avg_salary
FROM employees;
) dt
WHERE SALARY > avg_salary;
最后,市場上有兩個 RDBMS 有一個QUALIFY子句(Snowflake 和 Teradata),它們類似于WHEREorHAVING子句,允許視窗函式成為過濾器的一部分。如果您使用這兩個平臺之一,那么您可以將其撰寫為單個 SELECT 陳述句:
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
FROM employees
QUALIFY SALARY > AVG(SALARY) OVER ();
就像WHERE在執行開始時的行為一樣,在HAVING接近執行結束時的QUALIFY行為,甚至比那更晚(就在之前ORDER BY)。奇怪的是,這正是您最初想要的,并且一些 RDBMS 已經預料到了您的需求。我希望更多的 RDBMS 在未來的版本中采用 QUALIFY 子句,因為它非常方便。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/467828.html
