1. 程式人生 > >統計函式應用之SQL 分析函式

統計函式應用之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層的平均值來與當月資料做對比分析,稱求【逐層平均值】。遇到類似需求時候,該如何處理呢?如圖所示:

222

二、實現思路編輯

在建立資料集時用sql的開窗排名函式[AVG(欄位) over(PARTITION BY 分組欄位 order by 逐層欄位)]處理,然後進行直接呼叫。

  1. SELECT t.*,AVG(t.銷量) over(PARTITION BY t.年份 order by t.月份) as '前N月平均銷量'  FROM 大陸車輛銷售 t;      

三、示例編輯

3.1 初始資料

開啟軟體自帶的FRDemo庫中的【大陸汽車銷售】表:

222

3.2 逐層平均值sql指令碼

  1. SELECT t.*,AVG(t.銷量) over(PARTITION BY t.年份 order by t.月份) as '前N月平均銷量'  FROM 大陸車輛銷售 t;      

3.3 效果預覽

執行SQL指令碼,效果如下:

222

————————————————————————————————————————————————————

2.有時我們在設計報表的過程中,可能會遇到這樣的需求:將資料按照某一欄位平均分組,比如一張成績表(100人)按某一科目成績(高低)順序分為4組,將第一組-優,第二組-良,第三組-較差,第四組-不及格 的情況。像這樣需要將一個有序整體按照一定的比例劃分資料的情況。

一般思路:先將成績按照一定順序排名後按名次平均分為4組,1-25名為第一組,26-50為第二組,51-75為第三組,76-100為第四組,最後給對應所在組評級。這種實現思路太過於繁瑣,實現起來也較難!今天分享一個快速實現的函式【NTILE函式】,使用它可以起到事半功倍的效果。

222

2. 思路編輯

在資料集中用sql的【NTILE (N) OVER(ORDER BY 欄位)】函式處理,然後進行直接呼叫。

注:NTILE(Num),Num為要等分的組數(量)。

語句結構:

  1. CASE NTILE (N) OVER (ORDER BY GRADE DESC)  
  2. WHEN 1 THEN  
  3.     'A'  
  4. WHEN 2 THEN  
  5.     'B'  
  6. WHEN 3 THEN   
  7.         'C'  
  8. WHEN 4 THEN  
  9.     'D'  
  10.    . . .  
  11. WHEN N THEN  
  12.     'X'  
  13. END  

3. 示例編輯

3.1 準備資料

開啟SQL Server庫中的【STSCORE】表:

222

3.2 NTILE (N)實現的Sql

  1. SELECT  
  2.     STUDENTNO AS 學號,  
  3.     GRADE AS 科目,  
  4.     CASE NTILE (4) OVER (ORDER BY GRADE DESC)  
  5. WHEN 1 THEN  
  6.     '優'  
  7. WHEN 2 THEN  
  8.     '良'  
  9. WHEN 3 THEN '較差'  
  10. WHEN 4 THEN  
  11.     '不及格'  
  12. END AS '級別'  
  13. FROM  
  14.     "STSCORE"  
  15. WHERE  
  16.     COURSE = 'Chemistry'  
  17. ORDER BY  
  18.     STUDENTNO;  

注:case when then else end 用法請參考:CASE用法

3.3 效果預覽

執行SQL指令碼,效果如下:

222

——————————————————————————————————————————————————————

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構建表:

  1. -- ----------------------------  
  2. -- Table structure for ZSH_170222  
  3. -- ----------------------------  
  4. DROP TABLE [dbo].[ZSH_170222]  
  5. GO  
  6. CREATE TABLE [dbo].[ZSH_170222] (  
  7. [PART] varchar(255) NULL ,  
  8. [NAME_C] varchar(255) NULL ,  
  9. [PAY] int NULL   
  10. )  
  11. GO  
  12. -- ----------------------------  
  13. -- Records of ZSH_170222  
  14. -- ----------------------------  
  15. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'小明', N'9741')  
  16. GO  
  17. GO  
  18. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'小蘭', N'6908')  
  19. GO  
  20. GO  
  21. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'李東', N'6336')  
  22. GO  
  23. GO  
  24. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'楊瀾', N'9089')  
  25. GO  
  26. GO  
  27. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'黃偉', N'1646')  
  28. GO  
  29. GO  
  30. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'趙麗', N'4486')  
  31. GO  
  32. GO  
  33. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'技術部', N'張軍', N'3538')  
  34. GO  
  35. GO  
  36. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉偉', N'2143')  
  37. GO  
  38. GO  
  39. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'張強', N'6522')  
  40. GO  
  41. GO  
  42. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃渤', N'1247')  
  43. GO  
  44. GO  
  45. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'趙麗', N'7975')  
  46. GO  
  47. GO  
  48. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉東', N'2990')  
  49. GO  
  50. GO  
  51. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'張偉', N'4266')  
  52. GO  
  53. GO  
  54. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃俊', N'4815')  
  55. GO  
  56. GO  
  57. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'黃偉', N'7788')  
  58. GO  
  59. GO  
  60. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉康', N'4605')  
  61. GO  
  62. GO  
  63. INSERT INTO [dbo].[ZSH_170222] ([PART], [NAME_C], [PAY]) VALUES (N'綜合部', N'劉冰', N'6184')  
  64. GO  
  65. GO  

222

4.2 使用分析函式進行分析

執行sql:

  1. SELECT  
  2.     part,  
  3.     name_c,  
  4.     pay,  
  5.   CUME_DIST () OVER (ORDER BY pay) AS cat_1,  
  6.     CUME_DIST () OVER (PARTITION BY part ORDER BY pay) AS cat_2  
  7. FROM  
  8.     ZSH_170222  
  9. ORDER BY  
  10.     part,  
  11.     pay    

結果預覽與分析:

222

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