2016-03-04 81 views
1

這是我的查詢:在GROUP使用SELECT'd Case語句的COLUMNNAME BY

SELECT d.DeptName, CASE WHEN e.WorkCity is NULL THEN 'Mobile' 
              ELSE 'Stationary' 
         END AS EmpType, 
     AVG(e.MonthlyPayScale) AS AvgMnthPay 
FROM Department d, Employee e 
WHERE d.DeptId = e.DeptId 
GROUP BY d.DeptName, EmpType 
ORDER BY d.DeptName, EmpType 

這是我的輸出,這似乎是正確的:

deptname | emptype |  avgmnthpay 
----------+------------+------------------------ 
EvanDept | Mobile  | 7500.0000000000000000 
MaxDept | Stationary | 11250.0000000000000000 
PaulDept | Mobile  | 5000.0000000000000000 
PaulDept | Stationary | 12500.0000000000000000 
(4 rows) 

它通過部門名稱和移動組/固定員工,並計算每個組員工的平均月薪。

據我瞭解,雖然,這是SQL查詢的順序:

FROM 
WHERE 
GROUP BY 
SELECT 
ORDER BY 

所以GROUP BY語句發生 SELECT語句前。那麼,爲什麼:

GROUP BY d.DeptName,的empType

知道有關的empType任何東西,這是在SELECT語句中的CASE語句聲明?

所以基本上,爲什麼做我的代碼工作時GROUP BY前評估SELECT?

+0

我的SQL [擴展了'GROUP BY'子句](http://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html)在一個方式的數量,這是其中之一(在頁面的底部鏈接)。我不知道MySQL查詢編譯的內部工作原理,所以雖然你所說的操作順序是正確的,(雖然缺少'HAVING'),但我無法準確解釋擴展工作的原因。 – GarethD

+0

使用的標記dbms。涉及到GROUP BY時,MySQL和Postgresql有很大不同。 – jarlh

+0

一般提示(獨立於dbms):'GROUP BY d.DeptName,e.WorkCity'。 – jarlh

回答

0

您描述的處理常常用於解釋查詢的編譯以及何時已知什麼標識符。 SQL Server對此非常明確,其規則記錄在here

只是因爲SQL Server這樣做,並不意味着所有的數據庫都這樣做。

因此,不同的數據庫在允許各個子句中的列別名時更好或更差。 MySQL和Postgres允許GROUP BYHAVING子句中的列別名; Oracle和SQL Server不這樣做。所有數據庫都允許ORDER BY中的列別名。實際上,一些(如Hive)需要列別名並且不允許聚合函數。

我相信ANSI標準有話要說這個話題。它是否真正明確是另一個問題,但不同的數據庫有不同的個性。

而且,本討論涉及查詢的分析的詞彙。實際執行順序與原始聲明無關。大多數數據庫引擎使用數據流引擎,數據流操作符和SQL構造之間不存在一對一的對應關係。

1

執行CASE表達派生表:

select DeptName, EmpType, AVG(MonthlyPayScale) AS AvgMnthPay 
FROM 
(
    SELECT d.DeptName as DeptName, 
     CASE WHEN e.WorkCity is NULL THEN 'Mobile' 
       ELSE 'Stationary' 
     END AS EmpType, 
     e.MonthlyPayScale as MonthlyPayScale 
    FROM Department d 
     JOIN Employee e ON d.DeptId = e.DeptId 
) 
GROUP BY DeptName, EmpType 
ORDER BY DeptName, EmpType 

也沒有切換到現代,明確JOIN語法。更容易編寫(沒有錯誤),更易於閱讀和維護,並且如果需要,也更容易轉換爲外連接!

+0

我的問題更多地沿着**的原因**當GROUP BY在SELECT之前求值時,我的代碼是否工作? – Silent

+0

根據ANSI SQL標準,您的查詢不應起作用。我猜Postgresql的開發人員有太多的人要求這個有點奇怪的擴展 - 調整到一個非常普通的初學者的編程錯誤......(其他幾個dbms產品也有這個擴展。) – jarlh

1

答案是Postgresql中的名稱解析允許這樣做。

從Postgresql 9.3文檔(第7.2.3節。在GROUP BY和HAVING子句):

在嚴格的SQL,GROUP BY只能由源表 但PostgreSQL的擴展這也讓GROUP BY到組通過在選擇列表列 列組。也可以使用值表達式而不是簡單的 列名進行分組。

Link