SQL Server中的排名函数与分析函数详解

一、排名开窗函数概述

SQL Server的排名函数是对查询的结果进行排名和分组,TSQL共有4个排名函数,分别是:ROW_NUMBER、RANK、DENSE_RANK和NTILE。

他们和OVER()函数搭配使用,按照特定的顺序排名。

排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用。

  • PARTITION BY用于将结果集进行分组,开窗函数应用于每一组。
  • ODER BY 指定排名开窗函数的顺序。在排名开窗函数中必须使用ORDER BY语句。

1、ROW_NUMBER:行号

为每一组的行按顺序生成一个唯一的序号。

序列从1开始,按照顺序依次 +1 递增。分组内序列的最大值就是该分组内的行的数目。

ROW_NUMBER ( ) OVER ( [ PARTITION_BY_clause ] order_by_clause )

2、RANK:排名

也为每一组的行生成一个序号,但如果按照ORDER BY的排序,如果有相同的值会生成相同的序号,并且接下来的序号是不连续的。

例如,班级中,A,B分数都是100分,C的分数是90分,那么A和B的排名是1,C的排名是3。

3、DENSE_RANK:密集排名

和RANK(排名)类似,不同的是如果有相同的序号,那么接下来的序号不会间断。

例如,班级中,A,B分数都是100分,C的分数是90分,那么A和B的排名是1,C的排名是2

4、NTILE :分组排名

按照指定的数目将数据进行分组,并为每一组生成一个序号。

特别地,NTILE(4) 把一个分组分成4份,叫做Quartile。例如,以下脚本显示各个排名函数的执行结果:

select Department
    ,LastName
    ,Rate
    ,row_number() over(order by Rate) as [row number]
    ,rank() over(order by rate) as rate_rank
    ,dense_rank() over(order by rate) as rate_dense_rank
    ,ntile(4) over(order by rate) as quartile_by_rate
from #data

二、分析函数

分析函数基于分组,计算分组内数据的聚合值,经常会和窗口函数OVER()一起使用,使用分析函数可以很方便地计算同比和环比,获得中位数,获得分组的最大值和最小值。

分析函数和聚合函数不同,不需要GROUP BY子句,对SELECT子句的结果集,通过OVER()子句分组。

注意:distinct子句的执行顺序是在分析函数之后。

使用以下脚本插入示例数据:

;with cte_data as
(
select 'Document Control' as Department,'Arifin' as LastName,17.78 as Rate
union all
select 'Document Control','Norred',16.82
union all
select 'Document Control','Kharatishvili',16.82
union all
select 'Document Control','Chai',10.25
union all
select 'Document Control','Berge',10.25
union all
select 'Information Services','Trenary',50.48
union all
select 'Information Services','Conroy',39.66
union all
select 'Information Services','Ajenstat',38.46
union all
select 'Information Services','Wilson',38.46
union all
select 'Information Services','Sharma',32.45
union all
select 'Information Services','Connelly',32.45
union all
select 'Information Services','Berg',27.40
union all
select 'Information Services','Meyyappan',27.40
union all
select 'Information Services','Bacon',27.40
union all
select 'Information Services','Bueno ',27.40
)
select Department,LastName,Rate into #data from cte_data
go

SQL Server中共有4类分析函数。

1、LAG和LEAD

在一次查询中,对数据表进行排序,把已排序的数据从上向下看作是一个序列,对当前行而言,在序列上方的为后,在序列下方的为前。

在同一分组内,对于当前行:

  • Lag()函数:用于获取从当前行开始向后(或向上)计数的第N行。
  • Lead()函数:用于获取从当前行开始向前(或向下)计数的第N行。
LAG (scalar_expression [,offset] [,default])    OVER ( [ partition_by_clause ] order_by_clause )
LEAD ( scalar_expression [ ,offset ] , [ default ] )  OVER ( [ partition_by_clause ] order_by_clause )

参数注释:

  • sclar_expression:标量表达式
  • offset:默认值是1,必须是正整数,对于LAG()函数表示从当前行(current row)回退的行数,对于LEAD()表示从当前行向前进的行数。
  • default :当offset超出分区范围时要返回的值。 如果未指定默认值,则返回NULL。 default可以是列,子查询或其他表达式,但必须跟sclar_expression类型兼容。

结果日期,这两个函数特别适合用于计算同比和环比。

select DepartMent ,LastName,Rate
    ,lag(Rate,1,0) over(partition by Department order by LastName) as LastRate
    ,lead(Rate,1,0) over(partition by Department order by LastName) as NextRate
from #data order by Department ,LastName

按照DepartMent进行分组,对Document Control这一小组进行分析:

  • 第一行,对于LastRate字段,向后不存在数据行,返回参数Default的值,字段NextRate的值是第二行的Rate字段的值。
  • 第二行,LastRate是第一行的Rate字段的值,NextRate是第三行的Rate字段的值。对于中间行,依次类推。
  • 最后一行,LastRate是倒数第二行的Rate字段的值,对于NextRate字段,由于最后一行向前不存在数据行,返回参数Default的值。

以下程序代码用来示范如何透过 LAG 函数来计算每一列与前一列的 c2 字段相差几天:

declare @t table
  (
      c1 int identity
      ,c2 date
  )

  insert into @t (c2)
  select '20120101'
  union all
  select '20120201'
  union all
  select '20120110'
  union all
  select '20120221'
  union all
  select '20120121'
  union all
  select '20120203'

  select c1,c2
      ,LAG(c2) OVER (ORDER BY c2) as previous_c2
      ,DateDiff(day,LAG(c2) OVER (ORDER BY c2),c2) as diff
  from @t
  order by c2

2、FIRST_VALUE和LAST_VALUE

SQL SERVER 2012引入的函数。

获取分组内排在最末尾的行和排在第一位的行:

LAST_VALUE ( [scalar_expression ) OVER ( [ partition_by_clause ] order_by_clause rows_range_clause )
FIRST_VALUE ( [scalar_expression ] ) OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )

例如:

select Department, LastName, Rate,
    row_number() over (partition by Department order by LastName) as FIRSTVALUE,
    first_value(Rate) over (partition by Department order by LastName  rows between unbounded preceding and unbounded following) as FIRSTVALUE,
    last_value(Rate) over (partition by Department   order by LastName   rows between unbounded preceding and unbounded following) as LASTVALUE
from #data
order by Department, LastName;

3、CUME_DIST 和PERCENT_RANK:累积分布和排名百分比

  • CUME_DIST() :小于等于当前值的行数/分组内总行数
  • PERCENT_RANK() :(分组内当前行的RANK值-1)/ (分组内总行数-1),排名值是RANK()函数排序的结果值。

以下代码,用于计算累积分布和排名百分比:

select Department,LastName ,Rate
    ,cume_dist() over(partition by Department order by Rate) as CumeDist
    ,percent_rank() over(partition by Department order by Rate) as PtcRank
    ,rank() over(partition by Department order by Rate asc) as rank_number
    ,count(0) over(partition by Department) as count_in_group
from #data
order by DepartMent
    ,Rate desc

解释:

首先,NULL都会被当作最小值。

1、cume_dist的计算方法:小于等于当前行值的行数/总行数

比如,第3行值为16.82,有4行的值小于等于16.82,本组总行数5行,因此CUME_DIST为4/5=0.8 。

再比如,第4行值为10.25,行值小于等于10.25的共2行,本组总行数5行,因此CUME_DIST为2/5=0.4 。

2、PERCENT_RANK的计算方法:当前RANK值-1/总行数-1 。

比如,第4行的RANK值为1,本组总行数5行,因此PERCENT_RANK为1-1/5-1= 0

再比如,第7行的RANK值为9,本组总行数10行,因此PERCENT_RANK为9-1/10-1=0.8888888888888889

4、PERCENTILE_CONT和PERCENTILE_DISC:百分位的数值

PERCENTILE_CONT和PERCENTILE_DISC都是为了计算百分位的数值,比如计算在某个百分位时某个栏位的数值是多少。

  • PERCENTILE_CONT是连续型,CONT代表continuous,连续值,意味它考虑的是区间,所以值是绝对的中间值;
  • PERCENTILE_DISC是离散型,DISC代表discrete,离散值。所以它更多考虑向上或者向下取舍,而不会考虑区间。

以下脚本用于获得分位数:

select Department  ,LastName  ,Rate
    ,PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Rate) OVER (PARTITION BY Department) AS MedianCont
    ,PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY Rate) OVER (PARTITION BY Department) AS MedianDisc
    ,row_number() over(partition by Department order by Rate) as rn
from #data order by DepartMent ,Rate asc

到此这篇关于SQL Server排名函数与分析函数的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SqlServer2012中LEAD函数简单分析

    LEAD函数简单点说,就是把下一行的某列数据提取到当前行来显示,看示例更能解释清楚,先看测试用脚本 DECLARE @TestData TABLE( ID INT IDENTITY(1,1), Department VARCHAR(20), LastName VARCHAR(20), Rate FLOAT ) INSERT INTO @TestData(Department,LastName,Rate) SELECT 'Document Control','Arifin',17.7885 UNI

  • SQL Server日期加减函数DATEDIFF与DATEADD用法分析

    本文实例讲述了SQL Server日期加减函数DATEDIFF与DATEADD用法.分享给大家供大家参考,具体如下: SQL Server 日期的加减函数: DATEDIFF    DATEADD DATEDIFF: 返回跨两个指定日期的日期边界数和时间边界数, 语法:DATEDIFF ( datepart , startdate , enddate ) 用 enddate 减去 startdate 注:datepart 指定应在日期的哪一部分计算差额的参数,其日期相减时,只关注边界值,例: S

  • SqlServer 2005的排名函数使用小结

    尽管从技术上讲,其它排名函数的计算与ROW_NUMBER类似,但它们的的实际应用却少很多.RANK和DENSE--RANK主要用于排名和积分.NTILE更多地用于分析. 先创建一个示例表: 复制代码 代码如下: SET NOCOUNT ON USE [tempdb] IF OBJECT_ID('Sales')IS NOT NULL DROP TABLE sales CREATE TABLE Sales ( empid VARCHAR(10) NOT NULL PRIMARY KEY, mgrid

  • SqlServer2012中First_Value函数简单分析

    First_Value返回结果集中某列第一条数据的值,跟TOP 1效果一样,比较简单的一个函数 先贴测试用代码 DECLARE @TestData TABLE( ID INT IDENTITY(1,1), Department VARCHAR(20), LastName VARCHAR(20), Rate FLOAT ) INSERT INTO @TestData(Department,LastName,Rate) SELECT 'Document Control','Arifin',17.78

  • SQL SERVER修改函数名容易引发的问题分析

    1. 问题 今天遇到一个奇怪的问题:使用sp_helptext XXX查询出来的函数定义名竟然跟函数名不同,而sp_helptext实际是查询sys.all_sql_modules这个系统视图的.直接查询这个视图的definition字段,发现跟sp_helptext是一样的.难道是系统视图也存在缓存之类的机制?或者是个BUG?对于第一个问题,当时情况紧急,没有时间去求证是否存在了.第二个问题,我想没什么可能,SQL SERVER发展到今天(SQL 2016正式版准备推出,我使用的环境则是SQL

  • 实例讲解sql server排名函数DENSE_RANK的用法

    一.需求 之前sql server 的排名函数用得最多的应该是RoW_NUMBER()了,我通常用ROW_NUMBER() + CTE 来实现分页:今天逛园,看到另一个内置排名函数还不错,自己顺便想了一个需求,大家可以花1分钟先想想要怎么实现. 需求很简单:求成绩排名前五的学生信息. 例如: 由于成绩可以并列,所以前五名可能有多个.例如: 测试数据: declare @t table (ID int, StudentName nvarchar(15), Score int) insert int

  • SQL SERVER函数之深入表值函数的处理分析

    有些情况可能用下表值函数,表值函数主要用于数据计算出来返回结果集,可以带参数(和视图的一个大的区别),如果函数中没有过多的逻辑处理,如变量的定义,判断等,表值函数返回结果集可以简单向下面这么写: 复制代码 代码如下: CREATE FUNCTION Fun_GetReportNews(@type varchar(10))RETURNS TABLEAS RETURN(  SELECT TPR_ID,TPR_Title,TPR_Date FROM TP_ReportNews WHERE TPR_Ty

  • SQLServer RANK() 排名函数的使用

    本文主要介绍了SQLServer RANK() 排名函数的使用,具体如下: -- 例子表数据 SELECT * FROM test; -- 统计分数 SELECT name,SUM(achievement) achievement FROM test GROUP BY name; -- 按统计分数做排行 SELECT RANK() OVER( ORDER BY SUM(achievement) desc) 排行,name,SUM(achievement) achievement FROM tes

  • SQL Server中的排名函数与分析函数详解

    一.排名开窗函数概述 SQL Server的排名函数是对查询的结果进行排名和分组,TSQL共有4个排名函数,分别是:ROW_NUMBER.RANK.DENSE_RANK和NTILE. 他们和OVER()函数搭配使用,按照特定的顺序排名. 排名开窗函数可以单独使用ORDER BY 语句,也可以和PARTITION BY同时使用. PARTITION BY用于将结果集进行分组,开窗函数应用于每一组. ODER BY 指定排名开窗函数的顺序.在排名开窗函数中必须使用ORDER BY语句. 1.ROW_

  • SQL Server中日期时间函数的用法详解

    1.getdate():获取当前日期 返回当前SQLServer服务器所在计算机的日期和时间.返回值舍入到最近的秒小数部分,精度为.333秒数据库十七偏移量不包含在内. select getdate() --输出 2013-03-09 15:16:00.570 2.getutcdate():获取UTC时间值 select GETUTCDATE() -- 2013-06-18 08:02:53.253 3.year():获取年度信息 year函数以int数据类型的格式返回特定日期的年度信息.其中的

  • SQL Server中identity(自增)的用法详解

    一.identity的基本用法 1.含义 identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给identity修饰的字符赋值,否则编译时会报错 2.语法 列名 数据类型 约束 identity(m,n) m表示的是初始值,n表示的是每次自动增加的值 如果m和n的值都没有指定,默认为(1,1) 要么同时指定m和n的值,要么m和n都不指定,不能只写其中一个值,不然会出错 3.实例演示 不指定m和n的值 create table student1 ( sid int p

  • SQL Server中row_number分页查询的用法详解

    ROW_NUMBER()函数将针对SELECT语句返回的每一行,从1开始编号,赋予其连续的编号.在查询时应用了一个排序标准后,只有通过编号才能够保证其顺序是一致的,当使用ROW_NUMBER函数时,也需要专门一列用于预先排序以便于进行编号. ROW_NUMBER() 说明:返回结果集分区内行的序列号,每个分区的第一行从1开始. 语法:ROW_NUMBER () OVER ([ <partition_by_clause> ] <order_by_clause>) . 备注:ORDER

  • Sql server中内部函数fn_PhysLocFormatter存在解析错误详解

    前言 有网友指出,SQL Server 2012中fn_PhysLocFormatter内部函数在解析数据行记录位置时存在错误,见:http://www.itpub.net/thread-1751655-1-1.html,实际测试后发现,一是2008R2中同样存在问题,二是不仅页号解析存在问题,槽号解析也存在同样问题. 下面先查看表NT_SiteInfo的数据行记录位置. select SiteID,%%physloc%%,sys.fn_PhysLocFormatter(%%physloc%%)

  • SQL SERVER中常用日期函数的具体使用

    1 GETDATE() 返回当前系统日期 SELECT GETDATE() 2 DATEADD(日期部分,常数,日期) 返回将日期的指定日期部分加常数后的结果返回 常数为正 SELECT DATEADD(YY,1,GETDATE()) 等同于 SELECT DATEADD(YEAR,1,GETDATE()) 常数为负数 SELECT DATEADD(YY,-2,GETDATE()) 常数为小数(直接舍去小数部分) SELECT DATEADD(YY,2.4,GETDATE()) SELECT D

  • 关于numpy中np.nonzero()函数用法的详解

    np.nonzero函数是numpy中用于得到数组array中非零元素的位置(数组索引)的函数.一般来说,通过help(np.nonzero)能够查看到该函数的解析与例程.但是,由于例程为英文缩写,阅读起来还是很费劲,因此,本文将其英文解释翻译成中文,便于理解. 解释 nonzero(a) 返回数组a中非零元素的索引值数组. (1)只有a中非零元素才会有索引值,那些零值元素没有索引值: (2)返回的索引值数组是一个2维tuple数组,该tuple数组中包含一维的array数组.其中,一维arra

  • python3中datetime库,time库以及pandas中的时间函数区别与详解

    1介绍datetime库之前 我们先比较下time库和datetime库的区别 先说下time 在 Python 文档里,time是归类在Generic Operating System Services中,换句话说, 它提供的功能是更加接近于操作系统层面的.通读文档可知,time 模块是围绕着 Unix Timestamp 进行的. 该模块主要包括一个类 struct_time,另外其他几个函数及相关常量. 需要注意的是在该模块中的大多数函数是调用了所在平台C library的同名函数, 所以

  • python使用numpy中的size()函数实例用法详解

    在python中,提到如何计算多维数组和矩阵,那一定会想到numpy.numpy定义了矩阵和数组,为它们提供了相关的运算.size中文解释为大家.尺寸的意思,如果想要统计矩阵元素个数,使用size()函数就可以解决. 1.Numpy size()函数 主要是用来统计矩阵元素个数,或矩阵某一维上的元素个数的函数. 2.使用语法 numpy.size(a, axis=None) 3.使用参数 a:输入的矩阵 axis:int型的可选参数,指定返回哪一维的元素个数.当没有指定时,返回整个矩阵的元素个数

  • Numpy中的shape函数的用法详解

    shape函数的功能是读取矩阵的长度,比如shape[0]就是读取矩阵第一维度的长度,相当于行数.它的输入参数可以是一个整数表示维度,也可以是一个矩阵.shape函数返回的是一个元组,表示数组(矩阵)的维度,例子如下: 1. 数组(矩阵)只有一个维度时,shape只有shape[0],返回的是该一维数组(矩阵)中元素的个数,通俗点说就是返回列数,因为一维数组只有一行,一维情况中array创建的可以看做list(或一维数组),创建时用()和[ ]都可以,多维就不可以这样子了,这里使用[ ],请看下

随机推荐