統計函式應用之SQL 分析函式
本文執行環境:Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
1.[AVG(欄位) over(PARTITION BY 分組欄位 order by 逐層欄位)]
2.NTILE函式 分組評優
3.語法:CUME_DIST( ) OVER ( [ partition_by_clause] order_by_clause )
目錄:
---------------------------------------------------------------------------
一、問題描述編輯
對於一些使用者而言,有時候需要對原始資料分組求每層(包含)所處前N層的平均值來與當月資料做對比分析,稱求【逐層平均值】。遇到類似需求時候,該如何處理呢?如圖所示:
二、實現思路編輯
在建立資料集時用sql的開窗排名函式[AVG(欄位) over(PARTITION BY 分組欄位 order by 逐層欄位)]處理,然後進行直接呼叫。
- SELECT t.*,AVG(t.銷量) over(PARTITION BY t.年份 order by t.月份) as '前N月平均銷量' FROM 大陸車輛銷售 t;
三、示例編輯
3.1 初始資料
開啟軟體自帶的FRDemo庫中的【大陸汽車銷售】表:
3.2 逐層平均值sql指令碼
- SELECT t.*,AVG(t.銷量) over(PARTITION BY t.年份 order by t.月份) as '前N月平均銷量' FROM 大陸車輛銷售 t;
3.3 效果預覽
執行SQL指令碼,效果如下:
————————————————————————————————————————————————————
2.有時我們在設計報表的過程中,可能會遇到這樣的需求:將資料按照某一欄位平均分組,比如一張成績表(100人)按某一科目成績(高低)順序分為4組,將第一組-優,第二組-良,第三組-較差,第四組-不及格 的情況。像這樣需要將一個有序整體按照一定的比例劃分資料的情況。
一般思路:先將成績按照一定順序排名後按名次平均分為4組,1-25名為第一組,26-50為第二組,51-75為第三組,76-100為第四組,最後給對應所在組評級。這種實現思路太過於繁瑣,實現起來也較難!今天分享一個快速實現的函式【NTILE函式】,使用它可以起到事半功倍的效果。
2. 思路編輯
在資料集中用sql的【NTILE (N) OVER(ORDER BY 欄位)】函式處理,然後進行直接呼叫。
注:NTILE(Num),Num為要等分的組數(量)。
語句結構:
- CASE NTILE (N) OVER (ORDER BY GRADE DESC)
- WHEN 1 THEN
- 'A'
- WHEN 2 THEN
- 'B'
- WHEN 3 THEN
- 'C'
- WHEN 4 THEN
- 'D'
- . . .
- WHEN N THEN
- 'X'
- END
3. 示例編輯
3.1 準備資料
開啟SQL Server庫中的【STSCORE】表:
3.2 NTILE (N)實現的Sql
- SELECT
- STUDENTNO AS 學號,
- GRADE AS 科目,
- CASE NTILE (4) OVER (ORDER BY GRADE DESC)
- WHEN 1 THEN
- '優'
- WHEN 2 THEN
- '良'
- WHEN 3 THEN '較差'
- WHEN 4 THEN
- '不及格'
- END AS '級別'
- FROM
- "STSCORE"
- WHERE
- COURSE = 'Chemistry'
- ORDER BY
- STUDENTNO;
注:case when then else end 用法請參考:CASE用法。
3.3 效果預覽
執行SQL指令碼,效果如下:
——————————————————————————————————————————————————————
3. 函式介紹編輯
分析函式CUME_DIST():–CUME_DIST 小於等於當前值的行數/分組內總行數
語法:CUME_DIST( ) OVER ( [ partition_by_clause] order_by_clause )
解釋:通過 partition_by_clause 將劃分為分割槽函式應用到的 FROM 子句生成的結果集。 如果未指定,則此函式將查詢結果集的所有行視為單個組。 order_by_clause 確定在其中執行該操作的邏輯順序。 order_by_clause 是必需的。
返回型別:CUME_DIST 返回的值範圍大於 0 並小於或等於 1的數值。
4. 示例編輯
4.1 準備資料
使用以下SQL構建表:
- -- ----------------------------
- -- Table structure for ZSH_170222
- -- ----------------------------
- DROP TABLE [dbo].[ZSH_170222]
- GO
- CREATE TABLE [dbo].[ZSH_170222] (
- [PART] varchar(255) NULL ,
- [NAME_C] varchar(255) NULL ,
- [PAY] int NULL
- )
- GO
- -- ----------------------------
- -- Records of ZSH_170222
- -- ----------------------------
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'小明', N'9741')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'小蘭', N'6908')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'李東', N'6336')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'楊瀾', N'9089')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'黃偉', N'1646')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'趙麗', N'4486')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'張軍', N'3538')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉偉', N'2143')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'張強', N'6522')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃渤', N'1247')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'趙麗', N'7975')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉東', N'2990')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'張偉', N'4266')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃俊', N'4815')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃偉', N'7788')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉康', N'4605')
- GO
- GO
- INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉冰', N'6184')
- GO
- GO
4.2 使用分析函式進行分析
執行sql:
- SELECT
- part,
- name_c,
- pay,
- CUME_DIST () OVER (ORDER BY pay) AS cat_1,
- CUME_DIST () OVER (PARTITION BY part ORDER BY pay) AS cat_2
- FROM
- ZSH_170222
- ORDER BY
- part,
- pay
結果預覽與分析:
Cat_1: 沒有PARTITION BY ,在整個公司裡分析
所有資料均為1組,總行數為17
第一行(黃偉):小於等於1646的行數為2,因此,2/17= 0.117647058823529
第二行(張軍):小於等於3538的行數為5,因此,5/17= 0.294117647058824
第三行(趙麗):小於等於3538的行數為7,因此,7/17= 0.411764705882353
…
第十七行(趙麗君):小於等於7975的行數為15,因此,15/17= 0.882352941176471
Cat_2: 按照部門(技術部/綜合部)分析
技術組的行數為7,
第一行(黃偉):小於等於1646的行數為1,因此,1/7= 0.142857142857143
第二行(張軍):小於等於3538的行數為2,因此,2/7= 0.285714285714286
…
第七行(小明):小於等於9741的行數為7,因此,7/7= 1
綜合部的行數為10,
第一行(黃渤):小於等於1247的行數為1,因此,1/10= 0.1
第二行(劉偉):小於等於2142的行數為2,因此,2/10= 0.2
…
第十行(趙麗君):小於等於7975的行數為10,因此,10/10= 1