SQL高级聚集特性

本文介绍了SQL中的窗口函数,包括rank()、dense_rank()、row_number()、percent_rank()和cume_dist(),以及lag()和lead()函数的使用方法,展示了它们在数据排序、分组和计算排名中的应用。
摘要由CSDN通过智能技术生成
Markdown
SQLyog Ultimate 64
Authors
6s

参考 大学数据库university

排名(序号函数)

序号函数: ROW_NUMBER()、 RANK()、 DENSE_RANK(), 可以用来实现分组排序, 并添加序号

rank()

-- Examp_1: 对每个系的教师按照薪资排序, 并给出排名;
SELECT id, dept_name, salary,
rank() over(PARTITION BY dept_name
ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述

-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
rank() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述

rank函数对所有在order by属性上相等的元组赋予相同的名次,不连号

dense_rank()

-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
dense_rank() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述

dense_rank函数对所有在order by属性上相等的元组赋予相同的名次,连号

row_number()

-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
row_number() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述
比较instructor原数据:
在这里插入图片描述

row_number函数对行进行排序,并且按行在排序顺序中所处位置给每行一个唯一的行号,具有相同排序值得不同行按照非确定的方式来得到不同的行号

percent_rank()

-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
percent_rank() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述

一个元组的percent_rank以分数的形式给出了该元组的排名。

-- Examp_1: 对每个系的教师按照薪资排序, 并给出排名;
SELECT id, dept_name, salary,
percent_rank() over(PARTITION BY dept_name
ORDER BY salary DESC) AS 'Rank'
FROM instructor;

举例:
Biology分区中有两个元组

元组排名该元组的百分比排名
1(1-1)/(2-1)=0
2(2-1)/(2-1)=1

Comp.Sci分区中有三个元组

元组排名该元组的百分比排名
1(1-1)/(3-1)=0
2(2-1)/(3-1)=0.5
3(3-1)/(3-1)=1
-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
percent_rank() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor; 

在这里插入图片描述

如果分区中有n个元组且某元组的排名为r,则该元组的百分比排名定义为(r-1)/(n-1)(如果该分区中只有一个元组则定义为null)


假定对于某分区,n个元组,某元组排名为r, 则

元组排名该元组的百分比排名
r(r-1)/(n-1)

cume_dist( )

-- Examp_1: 查询小于等于当前薪资( salary) 的比例
SELECT id, dept_name, salary,
cume_dist() over(PARTITION BY dept_name
ORDER BY salary DESC) AS 'Rank'
FROM instructor;

在这里插入图片描述

-- Examp_2: 对所有的教师按照薪资排序, 并给出排名;
SELECT id, dept_name,salary,
cume_dist() over( ORDER BY salary DESC) AS 'Rank'
FROM instructor; 

在这里插入图片描述

cume_dist()(累积分布的简写)函数对于一个元组的定义是p/n, 其中p是分区中排序值小于或等于该元组排序值的元组数,并且n是分区中的元组数。

举例:
只有一个分区,元组数为15,n=15
所有元组的排序值从上到下依次1 2 3 3 5 6 7 7 9 10 11 12 13 14 15
(跳不跳数不影响,排序值肯定不连号)(结论推得,欢迎补充)

pp/n
11/15 ~0.06666666666
22/15~0.13333333333
44/15~0.26666666666
44/15~0.26666666666
55/15~0.33333333333
66/15=0.4
88/15~0.53333333333
88/15~0.53333333333
1515/15=1

> 有关排名的基本问题

如何处理多个元组在排序属性上取值相同的情况?

· rank函数对所有在order by属性上相等的元组赋予相同的名次,在排名中产生空挡(1134)
·dense_rank函数对所有在order by属性上相等的元组赋予相同的名次,不在排名中产生空挡(1123)
·row_number函数对行进行排序,每一行有唯一的行号(1234)

窗口函数

window

窗口查询在一定范围内的元组上计算聚集函数。该特性很有用,比如计算一个固定时间区间的聚集值,此时间区间被称为一个窗口

命令格式

窗口函数名( expr ) over (
partition by …
Order by …
frame_clause
)

参数说明
· expr 是字段表达式, 有些函数不需要参数;
· over 子句包含三个选项:
· 分区( partition by): 用于将数据行拆分成多个分区( 组),
类似于 group by 分组。 如果省略了 partition by, 所有的数
据作为一个组进行计算;
· 排序(ORDER BY): 用于指定分区内的排序方式;
· 窗口大小(frame_clause): 用于在当前分区内指定一个计算窗
口, 也就是一个与当前行相关的数据子集

语法

<窗口函数> over (partition by <用于分组的列名>
order by <用于排序的列名>
rows/range子句<用于定义窗口大小> )

<窗口函数>可以放以下两种函数:
1) 专用窗口函数,包括后面要讲到的rank, dense_rank, row_number等专用窗口函数。
2) 聚合函数,如sum. avg, count, max, min等

聚集函数+分窗

聚集函数(aggregate function)

是以值集(集合或多重集合)为输入并返回单个值的函数。
SQL提供了五个标准的固有聚集函数。
· 平均值:avg
· 最小值:min
· 最大值:max
· 总和:sum
· 计数:count

-- Examp_1: 查询每个教师的姓名, 所属系, 工资, 及所在系的累加工资;
SELECT NAME,dept_name,salary,
SUM(salary) over(PARTITION BY dept_name ORDER BY salary) AS v1
FROM instructor;

在这里插入图片描述

** 按系分区,区内按工资排序然后组内累加 **

--  Examp_2: 不使用 order by salary,默认把分组内的所有数据进行 sum操作;
SELECT NAME,dept_name,salary,
SUM(salary) over(PARTITION BY dept_name ) AS v1
FROM instructor;

在这里插入图片描述

** 按系分区,没有排名,区内累加**

-- Examp_3: 指定窗口大小;
SELECT id, dept_name,salary,
SUM(salary) over(ORDER BY salary ROWS BETWEEN 2 preceding AND current ROW) AS c1
FROM instructor;

在这里插入图片描述

rows or range

格式
[<ROWS or RANGE clause> BETWEEN <Start expr> AND <End expr>]
区分

·ROWS: 表示按照行的范围进行定义框架,根据order by子句排序后,取的前N行及后N行的数据计算(与当前行的值无关,只与排序后的行号相关。

边界可取值(Start expr & End expr)解释
Current Row当前行
n preceding前 n 行,n 为数字
unbounded preceding开头
n following后n行,n 为数字
unbounded following结尾

以3为例

SUM(salary) over(ORDER BY salary ROWS BETWEEN 2 preceding AND current ROW) AS c1

按salary排序后,取前两行到当前行数据做和

行数【sum】
1NULL
2NULL+46305.00=46305.00
3NULL+46305.00+69457.50=115762.50
446305.00+69457.50+71772.75=187535.25

·RANGE:表示按照值的范围进行定义框架,根据order by子句排序后,指定当前行对应值的范围取值,行数不固定,只要行值在范围内,对应行都包含在内。适用于对日期、时间、数值排序分组

range取特定日期区间说明
range interval 7-1 day preceding最近7天的值
range between interval 1 day preceding and interval 1 day following前后一天和当天的值
-- 求每个教师的薪资情况及对应+—10000薪资范围的人数
SELECT id, dept_name, salary,
COUNT(*) over(ORDER BY salary RANGE BETWEEN 10000 preceding AND 10000 following) AS '教师人数(~10000)'
FROM instructor;

薪资36305.00~56305.00的教师只有一个

在这里插入图片描述

分布函数- cume_dist()

定义

cume_dist()(累积分布的简写)函数对于一个元组的定义是p/n, 其中p是分区中排序值小于或等于该元组排序值的元组数,并且n是分区中的元组数。

用途

计算:分组内小于、 等于当前 rank 值的行数 / 分组内总行数

例解

-- Examp_1: 查询小于等于当前薪资( salary) 的比例;
SELECT id, dept_name,salary,
cume_dist() over(ORDER BY salary) AS r1,
cume_dist() over(PARTITION BY dept_name ORDER BY salary) AS r2
FROM instructor;

·按薪资进行排名,计算元组
·按系分区,按薪资排名,计算分区内元组

在这里插入图片描述

如 salary=79380.00, 全体教师中, 有 6个教师的工资<=79380.00,0.4*15=6
如salary=95917.50,全体教师中有10人工资<=95917.50,10/15=0.66666666
如salary=101430.00,Comp.Sci系教师工资都不超过101430.00,3/3=1

前后函数-lag 和 lead

用途

返回位于当前行的前 n 行(LAG(expr,n))或后 n 行(LEAD(expr,n))
的 expr 的值

例解

-- Examp_1: 查询前 1 名教师的工资和当前教师工资的差值;
SELECT id, dept_name, salary,
lag(salary,1) over(ORDER BY salary) AS r1
FROM instructor;

按薪资排序

在这里插入图片描述

-- Examp_2: 查询后 1 名教师的工资和当前教师工资的差值;
SELECT id, dept_name,salary,
lead(salary,1) over(ORDER BY salary) AS r1
FROM instructor;

在这里插入图片描述

上卷

上卷: with rollup
group by + with rollup: 表示在进行分组统计的基础上, 再次对每一小
组进行汇总统计。
————————————————————————————————-未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值