SQLServer · 特性分析 · SQL Server 2012的分析函数未必都理解透了(2)

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: --- title: SQLServer · 特性分析 · SQL Server 2012的分析函数未必都理解透了 author: 石沫 --- # 1. 背景 最近有用户在做一些项目,使用到SQL SERVER 2012的一些新特性,比如SQL SERVER 提供的8个非常有用的分析函数,一开始我看了相关的文档,感觉内容很多,理解不清楚,不透彻。而我现在想来,其实不需要那

title: SQLServer · 特性分析 · SQL Server 2012的分析函数未必都理解透了

author: 石沫

1. 背景

最近有用户在做一些项目,使用到SQL SERVER 2012的一些新特性,比如SQL SERVER 提供的8个非常有用的分析函数,一开始我看了相关的文档,感觉内容很多,理解不清楚,不透彻。而我现在想来,其实不需要那么清楚,我觉得值要理解他的基本用法就足以应对工作,下面根据我的理解,以最简单的方式解析这些分析函数。

5. 分析函数 LAG

微软定义:
访问相同结果集的先前行中的数据,而不使用 SQL Server 2012 中的自联接。 LAG 以当前行之前的给定物理偏移量来提供对行的访问。 在 SELECT 语句中使用此分析函数可将当前行中的值与先前行中的值进行比较。
还是比较拗口,最近有用户在做一些项目,我们还是看看示例比较好理解,看看是不是这样。

DECLARE
    @analytic TABLE( 
        name varchar(35) ,
        dept varchar(35),
        salary money ,
        hiredate date
    )
INSERT INTO @analytic 
        VALUES
--bd
('andy01','bd',15000,'2002-01-09'),
('andy02','bd',12000,'2003-01-09'),
('andy03','bd',12000,'2003-02-09'),
('andy04','bd',10000,'2005-05-09'),
('andy05','bd',8000,'2003-06-09'),
--ca
('andy06','ca',20000,'2003-01-09'),
('andy07','ca',18000,'2005-02-09'),
('andy08','ca',18000,'2005-03-09'),
('andy09','ca',15000,'2004-01-09'),
('andy10','ca',12000,'2003-06-09'),
('andy11','ca',12000,'2002-09-09'),
('andy12','ca',10000,'2003-07-09'),
('andy13','ca',8000,'2003-08-09'),
('andy14','ca',8000,'2003-11-09'),
('andy15','ca',8000,'2003-01-09')

SELECT 
    dept,name,hiredate,salary,
    LAG(salary,1,0) OVER(PARTITION BY dept ORDER BY salary) AS lag_,
    (LAG(salary,1,0) OVER(PARTITION BY dept ORDER BY salary)-salary) AS lag_diff_salary 
FROM @analytic

我们再看看结果:
5

从这个结果看,确实如此,与LEAD相反的行为。这里不多说了,从示例看的非常清楚。

6. 分析函数PERCENT_RANK

微软定义:
计算 SQL Server 2012 中一组行内某行的相对排名。 使用 PERCENT_RANK 计算一个值在查询结果集或分区中的相对位置。 PERCENT_RANK 类似于 CUME_DIST 函数。
只看这个,是看不出来啥意思的。我们还是从下面的实例可以看得很清楚:



DECLARE
    @analytic TABLE( 
        name varchar(35) ,
        dept varchar(35),
        salary money ,
        hiredate date
    )
INSERT INTO @analytic 
        VALUES
--bd
('andy01','bd',15000,'2002-01-09'),
('andy02','bd',15000,'2003-01-09'),
('andy03','bd',12000,'2003-02-09'),
('andy04','bd',10000,'2005-05-09'),
('andy05','bd',8000,'2003-06-09'),
--ca
('andy06','ca',20000,'2003-01-09'),
('andy07','ca',18000,'2005-02-09'),
('andy08','ca',18000,'2005-03-09'),
('andy09','ca',15000,'2004-01-09'),
('andy10','ca',12000,'2003-06-09'),
('andy11','ca',12000,'2002-09-09'),
('andy12','ca',10000,'2003-07-09'),
('andy13','ca',8000,'2003-08-09'),
('andy14','ca',8000,'2003-11-09'),
('andy15','ca',8000,'2003-01-09')

SELECT 
    dept,name,hiredate,salary,
     PERCENT_RANK() OVER(PARTITION BY dept ORDER BY salary) AS percent_rank_
FROM @analytic

6

从这个图可以清楚的:
最小的SALARY的 PERCENT_RANK() 始终是0,但有唯一一个最大SALARY是1.其他值的算法是这样的:
PERCENT_RANK() = 小于自己的记录数/(总的记录数-1)。这样来看是不是要简单清晰得多了。

7. 分析函数PERCENTILE_DISC

微软定义:
计算 SQL Server 2012 中整个行集内或行集的非重复分区内已排序值的特定百分位数。 对于给定的百分位数的值 P,PERCENTILE_DISC 对 ORDER BY 子句中表达式的值进行排序,并返回具有最小 CUME_DIST 值且大于或等于 P 的值(遵照相同的排序规范)。 例如,PERCENTILE_DISC (0.5) 将计算表达式的第 50 百分位数(也即中值)。 PERCENTILE_DISC 基于列值的离散分布来计算百分位数;结果等于列中的一个特定值。
好晦涩的说法,我也没有理解,我们还是看示例:



DECLARE
    @analytic TABLE( 
        name varchar(35) ,
        dept varchar(35),
        salary money ,
        hiredate date
    )
INSERT INTO @analytic 
        VALUES
--bd
('andy01','bd',15000,'2002-01-09'),
('andy02','bd',15000,'2003-01-09'),
('andy03','bd',12000,'2003-02-09'),
('andy04','bd',10000,'2005-05-09'),
('andy05','bd',8000,'2003-06-09'),
--ca
('andy06','ca',20000,'2003-01-09'),
('andy07','ca',18000,'2005-02-09'),
('andy08','ca',18000,'2005-03-09'),
('andy09','ca',15000,'2004-01-09'),
('andy10','ca',11000,'2003-06-09'),
('andy11','ca',1100,'2002-09-09'),
('andy12','ca',10000,'2003-07-09'),
('andy13','ca',8000,'2003-08-09'),
('andy14','ca',8000,'2003-11-09'),
('andy15','ca',8000,'2003-01-09')

SELECT 
    dept,name,hiredate,salary,
    CUME_DIST() OVER (PARTITION BY dept ORDER BY salary) cume_dist_ ,
    PERCENTILE_DISC (0.7) WITHIN GROUP( ORDER BY salary) 
    OVER(PARTITION BY dept) AS percentile_disc_
FROM @analytic

看看结果,我们来分析分析:

7

其实这个算法很简单:

  1. 首先要计算出CUME_DIST() 的值
  2. 其次要比较CUME_DIST() 的值和PERCENTILE_DISC (x)给定的x
  3. 如果CUME_DIST() 的值等于x,在各个分组上PERCENTILE_DISC (x)对应的值( ORDER BY *)

    都会等于对应的ORDER BY的salary值

    4.若CUME_DIST() 的值不等于x,在各个分组上PERCENTILE_DISC (x)对应的值( ORDER BY *)

都会等于接近于但大于x 的CUME_DIST() 值的ORDER BY的salary值(有点拗,不过看图就明白了)

8. 分析函数PERCENTILE_CONT

微软定义:
基于 SQL Server 2012 列值的连续分布计算百分位数。 将内插结果,且结果可能不等于列中的任何特定值。
同样,我们理解这句话存在困难,我们还是看看示例:



DECLARE
    @analytic TABLE( 
        name varchar(35) ,
        dept varchar(35),
        salary money ,
        hiredate date
    )
INSERT INTO @analytic 
        VALUES
--bd
('andy01','bd',15000,'2002-01-09'),
('andy02','bd',15000,'2003-01-09'),
('andy03','bd',12000,'2003-02-09'),
('andy04','bd',10000,'2005-05-09'),
('andy05','bd',8000,'2003-06-09'),
--ca
('andy06','ca',20000,'2003-01-09'),
('andy07','ca',18000,'2005-02-09'),
('andy08','ca',18000,'2005-03-09'),
('andy09','ca',15000,'2004-01-09'),
('andy10','ca',11000,'2003-06-09'),
('andy11','ca',1100,'2002-09-09'),
('andy12','ca',10000,'2003-07-09'),
('andy13','ca',8000,'2003-08-09'),
('andy14','ca',8000,'2003-11-09'),
('andy15','ca',8000,'2003-01-09')

SELECT 
    dept,name,hiredate,salary,
    CUME_DIST() OVER (PARTITION BY dept ORDER BY salary) cume_dist_ ,
    PERCENTILE_CONT(0.5) WITHIN GROUP( ORDER BY salary) 
    OVER(PARTITION BY dept) AS percentile_cont_
FROM @analytic

请看看下图:
8

这个函数可能不返回相同的值。 这是因为,PERCENTILE_CONT 内插适当的值,而无论它在数据集中是否存在,而 PERCENTILE_DISC 始终从数据集中返回实际值。
具体的算法,到目前,我还想得不是很清楚。读者可以自己推测一下这个算法的由来。

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
SQL API 数据库
数据库原理与应用(SQL Server)笔记 第十一章 游标
数据库原理与应用(SQL Server)笔记 第十一章 游标
数据库原理与应用(SQL Server)笔记 第十一章 游标
|
SQL 数据库
数据库原理与应用(SQL Server)笔记 第十章 用户定义函数
数据库原理与应用(SQL Server)笔记 第十章 用户定义函数
数据库原理与应用(SQL Server)笔记 第十章 用户定义函数
|
SQL 算法 Oracle
SQL Server 优化器内幕【上篇】
我记得我还在上一家公司的时候,有一次和主管一起做1:1,主管问我,将来你的技术方向是什么,我说我想往HA方向发展,因为是我的强项。主管问我还有别的吗?我犹豫地说,我也想做优化器方向,但是智商不够。主管大笑,说如果有兴趣可以钻研看看。
SQL Server 优化器内幕【上篇】
|
SQL 存储 NoSQL
SQL Server · 特性分析 · 2012列存储索引技术
摘要 MS SQL Server 2012首次引入了列存储索引(Columnstore Index)来加速数据分析(OLAP)和数据仓库(Data Warehouse)场景的查询,它主要是通过将数据按列压缩存储的方式来减少查询对磁盘IOPS开销和CPU开销,最终达到提升查询效率,降低响应时间的目的。当然,列存储索引也不是一把万能的钥匙,在SQL Server 2012版本中它有诸多非常严苛限制条件
1687 0
|
SQL 测试技术 Go
SQL Server · 特性介绍 · 统计信息
SQL Server查询优化器对于执行计划成本的评估是基于数据库统计信息的。所以,数据库统计信息直接影响到数据库查询效率,是数据库系统快速响应,低延迟特性的幕后英雄,但是我们又经常忽视数据库统计信息的存在和维护,怀着为英雄正名和唤醒大家对幕后英雄尊重的目的写作这篇文章。 什么是统计信息 SQL Server查询优化器使用统计信息来评估表或索引视图的一个或多个列中值的分布,这个分布信息提供了用于创
1577 0
|
SQL 存储 NoSQL
SQL Server · 特性介绍 · 聚集列存储索引
摘要 微软在SQL Server 2012引入了列存储技术,使得OLAP和Data warehouse场景性能提升10X,并且数据压缩能力超过传统表7X。这项技术包含三个方面的创新:列存储索引、Batch Mode Processing和基于Column Segment的压缩。但是,SQL Server 2012列存储索引的一个致命缺点是列存储索引表会进入只读状态,用户无法更新操作。SQL Ser
2990 0
|
SQL
SQLServer · 特性分析 · SQL Server 2012的分析函数未必都理解透了(1)
title: SQLServer · 特性分析 · SQL Server 2012的分析函数未必都理解透了 author: 石沫 1. 背景 最近有用户在做一些项目,使用到SQL SERVER 2012的一些新特性,比如SQL SERVER 提供的8个非常有用的分析函数,一开始我看了相关的文
2420 0