SQL 數據聚合

連續聚合

下面的例子將使用一個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
複製代碼

這裏使用的是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
複製代碼

 

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

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章