2013-01-01 83 views
14

任何人都可以解釋爲什麼我們不能用在group by條款窗口的功能以及它爲什麼只允許在SELECTORDER BY窗函數只能出現在SELECT或ORDER BY子句

我是想組根據記錄在row_number()和SQL Server作爲這樣的柱:

SELECT Invoice 
from table1 
group by row_number() over(order by Invoice),Invoice 

我得到一個錯誤

個窗函數只能出現在SELECT或ORDER BY

我可以選擇此row_number()在SELECT子句中,但我想知道爲什麼我們不能用它GROUP BY?

+3

通過'row_number()'分組有什麼意義?每個項目將獨立成組。不過,這個問題很合理。 – dasblinkenlight

+0

事情是考慮如果我有重複的發票,在這種情況下,我想保持這一點。你可以想一想爲什麼我應該分組。事情是我想爲什麼它是這樣的?爲什麼我們不能在組中使用窗口函數? – Mari

+0

它將如何產生歧義。你可以解釋嗎?如果我只想在where子句中選擇排名值2。如果它會造成模糊性 – Mari

回答

14

窗函數在ANSI規範定義的GROUP BYHAVINGWHERE的處理邏輯後執行。

更具體地說,它們在Logical Query Processing flow chart here的步驟5.1和6中被允許。

我想他們可以這樣來定義它的另一種方式,並允許GROUP BYWHEREHAVING使用窗口函數與窗口是合乎邏輯的結果設定在該階段的開始,但假設他們有和我們被允許建立這樣的查詢作爲

SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect 
    FROM YourTable 
    WHERE NTILE(2) OVER (PARTITION BY a ORDER BY b) > 1 
    GROUP BY a, 
      b, 
      NTILE(2) OVER (PARTITION BY a ORDER BY b) 
    HAVING NTILE(2) OVER (PARTITION BY a ORDER BY b) = 1 

有四個不同的邏輯窗口在播放好運運算出這將是什麼結果!另外,如果在HAVING中您實際上想要從上面的GROUP BY級別的表達式篩選,而不是以GROUP BY之後的結果行作爲窗口?

CTE版本更詳細,但也更明確,更易於遵循。

WITH T1 AS 
(
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForWhere 
    FROM YourTable 
), T2 AS 
(
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForGroupBy 
FROM T1 
WHERE NtileForWhere > 1 
), T3 AS 
(
SELECT a, 
     b, 
     NtileForGroupBy, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForHaving 
FROM T2 
GROUP BY a,b, NtileForGroupBy 
) 
SELECT a, 
     b, 
     NTILE(2) OVER (PARTITION BY a ORDER BY b) AS NtileForSelect 
FROM T3 
WHERE NtileForHaving = 1 

由於這些在SELECT語句都被定義和被混疊是容易實現的消除歧義從不同級別例如結果只需通過切換WHERE NtileForHaving = 1NtileForGroupBy = 1

+0

邏輯查詢處理流程圖非常豐富。感謝@Martin和你的解釋說明了很多,有道理:) – Mari

+0

現在的邏輯查詢處理流程圖..LINK中斷 – HaveNoDisplayName

+0

@HaveNoDisplayName如果你搜索''邏輯查詢處理海報「filetype:pdf'它看起來像一些人們製作了副本。 –

12

您可以解決這通過將窗函數在子查詢:

select invoice 
,  rn 
from (
     select Invoice 
     ,  row_number() over(order by Invoice) as rn 
     from Table1 
     ) as SubQueryAlias 
group by 
     invoice 
,  rn 
+0

是啊兄弟。我知道這一點,我擔心爲什麼我們不能在查詢中使用它?爲什麼它是以這種方式設計的? – Mari

+0

那麼,SQL Server甚至無法解析where子句中的簡單別名。例如,這不起作用:'選擇datediff(day,col1,col2)作爲來自YourTable的ddiff,其中ddiff> 1'。我認爲這是解析器的某種限制。 – Andomar

+0

嗯我從來不知道這一點。感謝您在此澄清:) – Mari

相關問題