理解OVER子句

来源:http://www.cnblogs.com/wenBlog/archive/2016/10/31/6015108.html
-Advertisement-
Play Games

簡介 Over子句在SQLServer 2005中回歸,並且在2012中得到了擴展。這個功能主要結合視窗函數來使用;也可以在序列函數“NEXT VALUE FOR”使用。OVER子句確定哪些來自查詢的列被應用到函數中,在函數中這些列被如何排序,並且何時重啟函數計算。由於篇幅限制,本篇僅僅就OVER子 ...


 

    簡介

    Over子句在SQLServer 2005中回歸,並且在2012中得到了擴展。這個功能主要結合視窗函數來使用;也可以在序列函數“NEXT VALUE FOR”使用。OVER子句確定哪些來自查詢的列被應用到函數中,在函數中這些列被如何排序,並且何時重啟函數計算。由於篇幅限制,本篇僅僅就OVER子句討論,不再深入各種函數了(提供幾個2014中新增的函數)。

語法:

<function> OVER (        [PARTITION BY clause]
                         [ORDER BY clause]
                         [ROWS or RANGE clause])

 

    這個語法中,顯示所有的子句都是可選的,實際上,每個函數使用OVER子句的函數都能確定哪個子句被允許哪個被需要。下圖是展示那些函數是允許或者需要的:

DB樂之者

R-需要, O-可選, X-不允許

 

PARTITION BY子句用來區分查詢結果集到數據子集中,或者分區。如果不使用PARTITION BY子句,整個來自查詢的結果集都將被使用。視窗函數被應用到每個獨立的分區數據,並且每個函數對於每個分區都是重新運算。通過定義一套確定分區的值來區分查詢到子集,這些值可以使列,標量函數,子查詢或者變數

舉例如下:

SELECT  COUNT(*)
FROM    [msdb].sys.indexes;

查詢結果如下:

2

 

這種情況下查詢僅僅返回一個數字,這就是msdb資料庫的索引的數量。現在讓我們加入OVER子句到這個查詢中:

SELECT  object_id, index_id, COUNT(*) OVER ()
FROM    [msdb].sys.indexes;

 

結果集如下:

3

 

這個查詢返回每個索引的對象ID和索引ID,並且還有結果集的索引總數。由於沒使用PARTITION BY子句,整個結果集都被當做一個分區。

現在我們加入PARTITION BY子句來看看結果如何改變:

SELECT  object_id, index_id, COUNT(*) OVER (PARTITION BY object_id)
FROM    [msdb].sys.indexes;

 

返回結果如下:

5

 

查詢返回每個索引的行數,但是現在查詢指定子句按照object_id 列來分區,因此count函數返回的是按object_id 分組的索引的數量。ORDER BY子句來控制排序。ROWS 或者 RANGE子句可以決定在分區內部的行數的子集。當使用ROWS 和 RANGE的時候,可以指定視窗函數的開始和結束點  ,如下圖所示:

 

6

有兩種語法指定視窗函數的範圍:

BETWEEN <beginning frame> AND <ending frame>
<beginning frame>

 

如果只有“開始點”,預設結束點為CURRENT ROW。

UNBOUNDED 關鍵字指定分區開端或者結束。CURRENT ROW 指定當前行是否是視窗的開始或者結束,這取決於視窗使用的位置。上圖中的“N”指定了之前當前列的或之後的行數。

下麵是有效規範的視窗函數:

-- 從分區中指定整個結果集
BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 

-- 指定五行,並且在當前行的前四行
BETWEEN 4 PRECEDING AND CURRENT ROW

-- 指定當前行到分區結束的所有行
BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

-- 指定從分區開始到當前行的所有行

UNBOUNDED PRECEDING 

 

 

 

為了展示以上說法,我們創建一些測試數據:兩個賬戶,每個賬戶四個日期,以及四個金額。然後執行查詢展示前面提到的語法的不同使用方式:

DECLARE @Test TABLE (
    Account     INTEGER,
    TranDate    DATE,
    TranAmount  NUMERIC(5,2));
INSERT INTO @Test (Account, TranDate, TranAmount)
VALUES  (1, '2015-01-01', 50.00),
        (1, '2015-01-15', 25.00),
        (1, '2015-02-01', 50.00),
        (1, '2015-02-15', 25.00),
        (2, '2015-01-01', 50.00),
        (2, '2015-01-15', 25.00),
        (2, '2015-02-01', 50.00),
        (2, '2015-02-15', 25.00);

SELECT  Account, TranDate, TranAmount,
        COUNT(*) OVER (PARTITION BY Account
                       ORDER BY TranDate
                       ROWS UNBOUNDED PRECEDING) AS RowNbr,
        COUNT(*) OVER (PARTITION BY TranDate) AS DateCount,
        COUNT(*) OVER (PARTITION BY Account
                       ORDER BY TranDate
                       ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS Last2Count
FROM    @Test
ORDER BY Account, TranDate;

 

  查詢返回如下結果:

7

 

    “RowNbr”列使用了count 函數返回分區後有多少行。這個分區是按照TranDate進行排序的,然後我們指定從分區的開始到當前行的視窗。對於第一行,‘2015-01-01’是第一行,座椅返回值就是1,然後第二行就是就是‘2015-01-15’,就是2,以此類推,其他這個賬戶的行往下排序。由於PARTITION BY 指定了Account 列,當Account 改變後這個函數被重置,於是可以看到Account 為2的時候RowNbr重新開始排序。

   “DateCount”列根據“date”分組分區展示有多少個相同的date值。例子中每個交易的日期都有兩個所以該列值都是2。與group by 相似,不同點是總的返回行數。尤其當計算當前行所占的總行數的百分比的時候應用比較多。

   “Last2Count” 列表示在分區內對於當前行和其前面一行的行數。有點拗口,具體點就是對於每個Account 最小date的數據就是第一行,那麼對於第一行距離第一行的計數就是1,其他行和都是計算它和它前面一行的數值都是2。比較常見的應用就是計算最近兩個月銷售的情況來計算獎金。

    此時,我們已經展示了ROWS的子句。我們通過下麵的例子可以快速理解兩者的不同(註意4和5行以及12和13行是相同的值,此處產生不同):

SELECT  FName,
        Salary,
        SumByRows  = SUM(Salary) OVER (ORDER BY Salary
                                        ROWS UNBOUNDED PRECEDING),
        SumByRange = SUM(Salary) OVER (ORDER BY Salary
                                       RANGE UNBOUNDED PRECEDING)
FROM    (VALUES (1, 'George',       800),
                (2, 'Sam',          950),
                (3, 'Diane',       1100),
                (4, 'Nicholas',    1250),
                (5, 'Samuel',      1250),
                (6, 'Patricia',    1300),
                (7, 'Brian',       1500),
                (8, 'Thomas',      1600),
                (9, 'Fran',        2450),
                (10,'Debbie',      2850),
                (11,'Mark',        2975),
                (12,'James',       3000),
                (13,'Cynthia',     3000),
                (14,'Christopher', 5000)
        ) dt(RowID, FName, Salary);

 

查詢結果如下:

DB樂之者

 

    後兩列的OVER子句除了ROWS/RANGE 的子句不同以外完全相同,註意,結束兩個的結束點都沒有指定,預設就是當前行。SumByRows 列通過計算第一行到當前行的所有行的值作為總數,而RANGE子句是計算到排序欄位(SALARY)的值相同的列的所有值得總和。所以當有重覆薪水值得時候就發現了兩者的不同,如上所示。

    重要提示:ORDER BY在OVER子句中只控制在視窗函數中使用分區行的順序,而不控制最終結果集的順序。如果需要制定結果集順序,還要在查詢後加上ORDER BY 語句。

下麵介紹幾種2014加入的新的視窗函數,以便我們使用,個人覺得很有幫助,性能非常不錯。

1.LAG() and LEAD()

–向前或者向後N行

2.FIRST_VALUE() 與 LAST_VALUE()

–第一行或最後一行

3.PERCENT_RANK() 與 CUME_DIST()

–計算排序(統計分析常用)

4.PERCENTILE_DISC() 與 PERCENTILE_CONT()

–根據百分比取值(統計分析)

 

總結:

本篇主要介紹了OVER的用法,通過對比不同關鍵字的對比展示如何使用。在很多缺少排序和分區分組的條件下,能夠簡化t-sql語句提高語句效率。希望對大家的使用有幫助。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 標簽: MongoDB 參考鏈接:[Windows上安裝MongoDB教程][1] 1. 官方下載 MongoDB提供了可用於32位和64位系統的預編譯二進位包,你可以從MongoDB官網下載安裝,MongoDB預編譯二進位包下載地址:http://www.mongodb.org/downloads ...
  • pt-ioprofile是用來觀察特定進程的IO信息的。 該腳本是用shell寫的,有兩方面的作用: 因實際依賴的是strace命令,該命令會對進程的性能造成較大的影響。所以,在負載較重的系統中,慎用。 使用方法: 直接執行pt-ioprofile即可,預設的是mysqld進程。 # pt-iopr ...
  • 我們先來看一下表中數據的情況: 需求: 把非魚類的產品都標記為99,鱸魚標記為2,非鱸魚的魚類標記為50. 步驟: 第一步:利用嵌套case 語句將非魚類標記為99 第二步:在魚類中,名稱為‘鱸魚’的標記為100 第三步:排除第一第二步之後,剩餘的標記為50,也就是非鱸魚的魚類標記為50. 整體的S ...
  • 新進的公司資料庫用DB2, 因為之前一直用ORGCLE,對DB2不太熟悉。 現在記錄一下在DB2中特殊函數的用法。 一. 要想實現ORACLE中 的同樣效果(DB2 多行一列轉換成 一行一列),在DB2中有三種實現方法。 1.1: SELECT [分組的欄位],LISTAGG([需要聚合的欄位名], ...
  • 原文鏈接:https://support.oracle.com/epmos/faces/DocumentDisplay?_adf.ctrlstate=23w4l35u5_4&id=1523934.1用途 提出問題,得到幫助並分享您的心得 排錯步驟 什麼是shared pool? 專用術語 Liter... ...
  • 01_1 mysql資料庫啟動與停止 以<管理員許可權>啟動cmd; 輸入net stop mysql停止mysql服務; 輸入net start mysql啟動mysql服務; 輸入mysql -u root –p回車,然後輸入密碼進入到mysql的操作系統,並具有root許可權; 在命令提示符視窗使 ...
  • 在一資料庫伺服器(Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64))發現有個作業調用Database Mail發送郵件時,有時候出現同樣的郵件發送兩封的情況,經過詳細檢查,排除了該作業裡面業務邏輯有問題的情況,確實存在重覆... ...
  • cmd命令netstat -ano 查看3306埠是否被占用 沒有的話 配置環境變數 path 追加D:\mysql\bin目錄 修改mysql目錄下my-default.ini basedir=D:\mysql datadir:D:\mysql\data cmd命令D:\mysql\bin\my ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...