你真的會玩SQL嗎?你所不知道的 數據聚合


 

你真的會玩SQL嗎?系列目錄

 

你真的會玩SQL嗎?之邏輯查詢處理階段

 

你真的會玩SQL嗎?和平大使 內連接、外連接

 

你真的會玩SQL嗎?三范式、數據完整性

 

你真的會玩SQL嗎?查詢指定節點及其所有父節點的方法

 

你真的會玩SQL嗎?讓人暈頭轉向的三值邏輯

 

你真的會玩SQL嗎?EXISTS和IN之間的區別

 

你真的會玩SQL嗎?無處不在的子查詢

 

你真的會玩SQL嗎?Case也瘋狂

 

你真的會玩SQL嗎?表表達式,排名函數

 

你真的會玩SQL嗎?簡單的 數據修改

 

你真的會玩SQL嗎?你所不知道的 數據聚合

 

你真的會玩SQL嗎?透視轉換的藝術

 

你真的會玩SQL嗎?冷落的Top和Apply

 

你真的會玩SQL嗎?實用函數方法匯總

 

你真的會玩SQL嗎?玩爆你的數據報表之存儲過程編寫(上)

 

你真的會玩SQL嗎?玩爆你的數據報表之存儲過程編寫(下)

 

 

 

本章的內容與 你真的會玩SQL嗎?透視轉換內容 非常重要,非常重要,非常重要 ,不理解的可以慢慢看,回頭看,過幾天再看,以后很多思想需要以此為基礎而演變。

此后用到的用例數據庫是SQL2008里面的,若看過本系列之前的文章,創建過基礎樣例數據庫就不用再創建。

若沒有創建過的,用例數據庫文件:鏈接:http://pan.baidu.com/s/1qW1QxA0 密碼:dqxx

 

連續聚合

下面的例子將使用一個EmpOrdersr匯總表,每位雇員在每個月占一行,包含該雇員在一個月內處理過的訂單數量,運行下代碼創建數據:

CREATE TABLE EmpOrders
    (
      empid INT NOT NULL ,
      ordmonth DATE NOT NULL ,--只取到月份2015-07-07
      qty INT NOT NULL ,
      PRIMARY KEY ( empid, ordmonth )
    )
go 
INSERT  INTO EmpOrders
        ( empid ,
          ordmonth ,
          qty 
        )
        SELECT  o.empid ,
                DATEADD(MONTH, DATEDIFF(MONTH, 0, o.orderdate), 0) AS ordmonth ,
                SUM(qty) AS qty
        FROM    Sales.Orders AS o
                JOIN Sales.OrderDetails AS od ON o.orderid = od.orderid
        GROUP BY empid ,
                DATEADD(MONTH, DATEDIFF(MONTH, 0, o.orderdate), 0)

查詢:

SELECT  empid ,
        ordmonth ,
        qty
FROM    EmpOrders
ORDER BY empid ,
        ordmonth

將輸出以下內容

接下來講講各類聚合……

1.累積聚合

 為每個雇員和每個月,返回從其開始有訂單操作以來到該月份處理過的訂單總量和每月的平均量,結果如下,怎么做?

SELECT  o1.empid ,
        o1.ordmonth ,
        o1.qty AS qtythismonth ,
        SUM(o2.qty) AS totalqty ,
        CAST(AVG(1. * o2.qty) AS NUMERIC(12, 2)) AS avgqty
FROM    EmpOrders AS o1
        JOIN EmpOrders AS o2 ON o2.empid = o1.empid
                                AND o2.ordmonth <= o1.ordmonth GROUP BY o1.empid ,
        o1.ordmonth ,
        o1.qty
ORDER BY o1.empid ,
        o1.ordmonth

 

若想得到雇員達到累積總量<1000之前的每月聚合值,怎么做?

 

SELECT  o1.empid ,
        o1.ordmonth ,
        o1.qty AS qtythismonth ,
        SUM(o2.qty) AS totalqty ,
        CAST(AVG(1. * o2.qty) AS NUMERIC(12, 2)) AS avgqty
FROM    EmpOrders AS o1
        JOIN EmpOrders AS o2 ON o2.empid = o1.empid
                                AND o2.ordmonth <= o1.ordmonth
GROUP BY o1.empid ,
        o1.ordmonth ,
        o1.qty
        HAVING SUM(o2.qty)<1000
ORDER BY o1.empid ,
        o1.ordmonth

 對總量做一次HAVING過濾 HAVING SUM(o2.qty)<1000,而不是用WHERE,因為過濾是的聚合,而不是屬性。  

 

2.滑動聚合

 滑動聚合是對序列內的一個滑動窗口進行的聚合計算,而不是從序列的開始計算到當前位置。

 求雇員最近三個月(包括本月)的平均訂單量(移動平均數),得到以下結果:

SELECT  o1.empid ,
        o1.ordmonth ,
        o1.qty AS qtythismonth ,
        SUM(o2.qty) AS totalqty ,
        CAST(AVG(1. * o2.qty) AS NUMERIC(12, 2)) AS avgqty
FROM    EmpOrders AS o1
        JOIN EmpOrders AS o2 ON o2.empid = o1.empid
                                AND (o2.ordmonth <= o1.ordmonth AND o2.ordmonth > DATEADD(MONTH,-3,o1.ordmonth))
GROUP BY o1.empid ,
        o1.ordmonth ,
        o1.qty
ORDER BY o1.empid ,
        o1.ordmonth
View Code

這里使用的是o2.ordmonth> 3個月之前的月份 and o2.ordmonth<=o1.當前月份

 

3.年初至今

聚合按年單位算,如求每個雇員每年內的每個月份的聚合,該怎樣寫?結果如下:

SELECT  o1.empid ,
       CONVERT( VARCHAR(7),o1.ordmonth ,121) AS  ordmonth,
        o1.qty AS qtythismonth ,
        SUM(o2.qty) AS totalqty ,
        CAST(AVG(1. * o2.qty) AS NUMERIC(12, 2)) AS avgqty
FROM    EmpOrders AS o1
        JOIN EmpOrders AS o2 ON o2.empid = o1.empid
                                AND ( o2.ordmonth <= o1.ordmonth
                                      AND o2.ordmonth >= CAST(CAST(YEAR(o1.ordmonth) AS CHAR(4))
                                      + '0101' AS DATETIME)
                                    )
GROUP BY o1.empid ,
        o1.ordmonth ,
        o1.qty
ORDER BY o1.empid ,
        o1.ordmonth
View Code

 

所有聚合函數都會忽略NULL值,只有一個例外:Count(*)

聚合中常見的函數為分組函數GROUP BY ,要注意的是 GROUP BY 原則 select后面所有列中 沒有使用聚合函數的列必須出現在GROUP BY 后面

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM