SQL Server窗口函數(shù):ROWS與RANGE
幾乎每次我展示SQL Server里的窗口時,人們都非常有興趣知道,當你定義你的窗口(指定的一組行)時,ROWS與RANGE選項之間的區(qū)別。因此在今天的文章里我想給你展示下這些選項的區(qū)別,對于你的分析計算意味著什么。
ROWS與RANGE之間的區(qū)別
當你用OVER()子句進行你的分析計算來打開你的窗口,你也可以在窗口里看到的,通過ROWS與RANGE選項來限制你的行數(shù)。來看下面的T-SQL語句:?
?1?SELECT ?2?????t.OrderYear, ?3?????t.OrderMonth, ?4?????t.TotalDue, ?5?????SUM(t.TotalDue)?OVER(ORDER?BY?t.OrderYear,?t.OrderMonth?ROWS?BETWEEN?UNBOUNDED?PRECEDING?AND?CURRENT?ROW)?AS?'RunningTotal' ?6?FROM ?7?( ?8?????SELECT ?9?????????YEAR(OrderDate)?AS?'OrderYear', 10?????????MONTH(OrderDate)?AS?'OrderMonth', 11?????????SalesPersonID, 12?????????TotalDue 13?????FROM?Sales.SalesOrderHeader? 14?)?AS?t 15?WHERE 16?????t.SalesPersonID?=?274 17?????AND?t.OrderYear?=?2005 18?GO
這個T-SQL語句用SUM()聚合函數(shù)進行匯總計算。窗口本身從第1行(UNBOUNDED PRECEDING)上至當前行(CURRENT ROW)。對于記錄級中的每1行,窗口變得越來越大,因此很容易進行匯總運算。下圖演示了這個概念。
從輸出你可以看到,結果是個自增長的匯總——運行合計匯總的結果。
現(xiàn)在假設你修改窗口為RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,會發(fā)生什么:
?1?SELECT ?2?????t.OrderYear, ?3?????t.OrderMonth, ?4?????t.TotalDue, ?5?????SUM(t.TotalDue)?OVER(ORDER?BY?t.OrderYear,?t.OrderMonth?RANGE?BETWEEN?UNBOUNDED?PRECEDING?AND?CURRENT?ROW)?AS?'RunningTotal' ?6?FROM ?7?( ?8?????SELECT ?9?????????YEAR(OrderDate)?AS?'OrderYear', 10?????????MONTH(OrderDate)?AS?'OrderMonth', 11?????????SalesPersonID, 12?????????TotalDue 13?????FROM?Sales.SalesOrderHeader? 14?)?AS?t 15?WHERE 16?????t.SalesPersonID?=?274 17?????AND?t.OrderYear?=?2005 18?GO
從下圖你可以看到,你得到了不同的結果,對于2005年11月的記錄顯示同樣的匯總。
我們來嘗試理解下為什么這里RANGE選項比ROWS選項給你不同的結果。使用ROWS選項你定義當前行的固定前后記錄。這里你看到的行取決于窗口的ORDER BY從句。你也可以說你在物理級別定義你的窗口。
當你使用RANGE選項事情就改變了。RANGE選項包含窗口里的所有行,和當前行有相同ORDER BY值。從剛才的圖片你可以看到,對于2005年11月的2條記錄你拿到同個匯總,因為這2行有同樣的ORDER BY值(2005年11月)。使用RANGE選項你在邏輯級別定義你的窗口。如果更多的行有同個ORDER BY值,當你使用ROWS選項你的窗口會包含更多的行。?
小結
在今天的文章里你看到了當你為你的分析計算定義窗口時,ROWS和RANGE選項之間的區(qū)別。使用ROWS選項你在物理級別定義在你窗口里有多少行。使用RANGE選項取決于ORDER BY值在窗口里有多少行被包含。因此當你使用RANGE選項時有性能上的巨大區(qū)別。在接下來的文章我會討論下這些副作用。