SQL SERVER 常用窗口函数RANK、DENSE_RANK、NTILE、ROW_NUMBER


一、窗口函数语法
窗口函数是整个SQL语句最后被执行的部分,这意味着窗口函数是在SQL查询的结果集上进行的,因此不会受到Group By, Having,Where子句的影响。
窗口函数的典型范例是我们在SQL Server 2005之后用到的排序函数,比如代码清单1所示。
Row_Number() OVER (partition by xx ORDER BY xxx desc) RowNumber
因此,我们可以把窗口函数的语法抽象出来,如代码清单2所示。
函数() Over (PARTITION By 列1,列2,Order By 列3,列4) AS 列别名
 
二、常用的窗口函数
1、ROW_NUMBER() ----分区行内排序    
     返回结果集分区内行的序列号,每个分区的第一行从开始。  ORDER BY子句可确定在特定分区中为行分配唯一ROW_NUMBER的顺序。
 
2、RANK()                 ----排名(间断)
     返回结果集的分区内每行的排名。行的排名是相关行之前的排名数加一。 如果某行与上一行的值一样,则将得到与上行相同的排名。
 
3、DENSE_RANK()  ----排名(不间断) 返回结果集分区中行的排名,在排名中没有任何间断。行的排名等于所讨论行之前的所有排名数加一。
如果有两个或多个行受同一个分区中排名的约束,则每个约束行将接收相同的排名。
 
4、NTILE()                 ----平均分组   将有序分区中的行分发到指定数目的组中。
各个组有编号,编号从一开始。对于每一个行,NTILE 将返回此行所属的组的编号。
 
5、LEAD()和LAG(),这是一对比较有趣的分析函数,这两个分析函数经过Order By子句排序后,可以在当前行访问上一行(LAG)或下一行(LEAD)的数据。
 
三、常用的窗口函数的实例
--1、创建测试数据表
CREATE TABLE #TMP_EMP_SALARY (DEPT VARCHAR(10),NAME VARCHAR(10), SALARY INT);
INSERT INTO #TMP_EMP_SALARY
SELECT '销售一部','曹操',   10000  UNION ALL
SELECT '销售一部','曹仁',   9000   UNION ALL
SELECT '销售一部','曹洪',   9000   UNION ALL
SELECT '销售一部','许褚',   8000    UNION ALL
SELECT '销售二部','典韦',   8000   UNION ALL
SELECT '销售二部','徐晃',   7000   UNION ALL
SELECT '销售二部','庞德',   6000   ;

--2、查看数据

SELECT * FROM #TMP_EMP_SALARY;

 

--3、查看所有人的,四个排名函数结果
SELECT          DEPT,NAME, SALARY,
        LAG(SALARY,1,0) OVER(ORDER BY SALARY DESC)                                        AS 'LAG_SALARY(上一行的值)',
        LEAD(SALARY,1,-1) OVER(ORDER BY SALARY DESC)                                      AS 'LEAD_SALARY(下一行的值)',
       ROW_NUMBER() OVER (ORDER BY SALARY DESC)                                  AS [ROW_NUMBER(排序)],
       RANK() OVER (ORDER BY SALARY DESC)                                   AS [RANK(排名(间断))],
       DENSE_RANK() OVER (ORDER BY SALARY DESC)                                  AS [DENSE_RANK(排名(不间断))],
       NTILE(3) OVER (ORDER BY SALARY DESC)                                  AS [NTILE(平均分组)],
       CAST(CAST(SALARY * 100.0 / SUM(SALARY) OVER () AS DECIMAL(18, 1)) AS VARCHAR(10)) + '%'                               AS 薪资占比,
       MAX(SALARY) OVER ()                                                         AS 最高薪资,
       MAX(SALARY) OVER () - SALARY                                      AS 最大差值,
       SALARY - MIN(SALARY) OVER ()                                     AS 最小差值,
       MIN(SALARY) OVER ()                                                             AS 最低薪资,
       AVG(SALARY) OVER ()                                                                           AS 平均薪资
  FROM #TMP_EMP_SALARY;

    

--4、查看各部门内,四个排名函数结果
SELECT   DEPT,NAME, SALARY,
       LAG(SALARY,1,0) OVER(PARTITION BY DEPT ORDER BY SALARY DESC)                              AS 'LAG_SALARY(上一行的值)',
       LEAD(SALARY,1,-1) OVER(PARTITION BY DEPT ORDER BY SALARY DESC)                             AS 'LEAD_SALARY(下一行的值)',
       ROW_NUMBER() OVER (PARTITION BY DEPT ORDER BY SALARY DESC)                              AS [ROW_NUMBER(排序)],
       RANK() OVER (PARTITION BY DEPT ORDER BY SALARY DESC)                                  AS [RANK(排名(间断))],
       DENSE_RANK() OVER (PARTITION BY DEPT ORDER BY SALARY DESC)                              AS [DENSE_RANK(排名(不间断))],
       NTILE(3) OVER (PARTITION BY DEPT ORDER BY SALARY DESC)                                 AS [NTILE(平均分组)],
       CAST(CAST(SALARY * 100.0 / SUM(SALARY) OVER (PARTITION BY DEPT) AS DECIMAL(18, 1)) AS VARCHAR(10)) + '%'AS 薪资占比,
       MAX(SALARY) OVER (PARTITION BY DEPT)                                             AS 最高薪资,
       MAX(SALARY) OVER (PARTITION BY DEPT) - SALARY                                       AS 最大差值,
       SALARY - MIN(SALARY) OVER (PARTITION BY DEPT)                                       AS 最小差值,
       MIN(SALARY) OVER (PARTITION BY DEPT)                                             AS 最低薪资,
       AVG(SALARY) OVER (PARTITION BY DEPT)                                             AS 平均薪资
  FROM #TMP_EMP_SALARY
  ORDER BY DEPT DESC, ROW_NUMBER() OVER (PARTITION BY DEPT ORDER BY SALARY DESC);

--5、删除临时表数据
DROP TABLE #TMP_EMP_SALARY;

 

 
  


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM