当前位置: 首页 > news >正文

Mysql-窗口函数二

文章目录

  • 1. 前百分之N的问题 排名 row_number
    • 1.1 需求
    • 1.2 准备工作
    • 1.3 分析
    • 1.4 实现
  • 2. 前百分之N的问题 ntile
    • 2.1 介绍
    • 2.2 语法
      • 2.2.1 示例
      • 2.2.2 结果示例
      • 2.2.3 注意事项
    • 2.3 需求
    • 2.4 分析
    • 2.5 实现
  • 3. 前百分之N的问题 百分比 PERCENT_RANK
    • 3.1 语法
      • 3.1.1 示例
      • 3.1.2 注意事项
    • 3.2 需求
    • 3.3 实现
  • 4. 偏移函数: 求环比增长率
    • 4.1 需求
    • 4.2 语法
    • 4.3 示例
    • 4.4 解释
    • 4.5 分析
    • 4.6 实现
    • 4.6 总结

1. 前百分之N的问题 排名 row_number

1.1 需求

  • 用户访问次数表,包含用户编号、用户类型、访问次数。
  • 要求在剔除访问次数前20%的用户后得到每类用户的平均访问次数。

1.2 准备工作

create table user_visits (user_id int,user_type varchar(32),visit_count int
)
;insert into user_visits
values
(10, 'A', 352),
(6, 'C', 209),
(7, 'C', 110),
(4, 'E', 101),
(2, 'B', 53),
(20, 'A', 53),
(11, 'C', 33),
(1, 'A', 30),
(9, 'E', 29),
(8, 'B', 6)
;

1.3 分析

在这里插入图片描述
在这里插入图片描述

1.4 实现

with t1 as(select user_id, user_type, visit_count,row_number() over (order by visit_count desc) as rn
from user_visits)
select distinct user_type,round(avg(visit_count) over(partition by user_type),1) as avg_cnt
from t1 where rn>(select count(*) from user_visits) * 0.2;

在这里插入图片描述

2. 前百分之N的问题 ntile

2.1 介绍

NTILE 是一个窗口函数,用于将查询结果划分为指定数量的分组,并为每个分组分配一个组号。这在分析数据时非常有用,尤其是需要对数据进行分组或均匀分配时。

2.2 语法

NTILE(num_buckets) OVER (PARTITION BY column ORDER BY column)
  • num_buckets:要将数据划分的组数(桶数)。
  • PARTITION BY column:可选,用于按指定列对数据进行分区。
  • ORDER BY column:必需,用于指定每个分区内的排序。

2.2.1 示例

假设我们有一个包含学生成绩的表 student_scores,结构如下:
在这里插入图片描述
准备数据

-- 创建表
CREATE TABLE students_score (student_id INT PRIMARY KEY,name VARCHAR(255),score INT
);-- 插入数据
INSERT INTO students_score (student_id, name, score) VALUES
(1, 'Alicia', 85),
(2, 'Robert', 90),
(3, 'Charles', 78),
(4, 'David', 92),
(5, 'Eva', 88);

将这些学生按分数划分为 3 组,并查看每个学生所属的组号。

SELECTstudent_id,name,score,NTILE(3) OVER (ORDER BY score DESC) AS group_number
FROMstudents_score;

2.2.2 结果示例

在这里插入图片描述
在这个例子中,NTILE(3) 将数据划分为 3 组,并根据分数的降序排序为每个学生分配一个组号。前两个最高分的学生被分配到第一组(组号1),接下来的两个学生被分配到第二组(组号2),而分数最低的学生被分配到第三组(组号3)。

2.2.3 注意事项

  • 如果不能均匀分配组,则较小编号的组可能会多出一行。例如,如果有 10 行数据和 3 组,则前两个组将有 4 行数据,最后一个组将有 2 行数据。
  • NTILE 通常用于数据分析场景,例如分配排名、分层抽样等。

2.3 需求

  • 用户访问次数表,包含用户编号、用户类型、访问次数。
  • 要求在剔除访问次数前20%的用户后得到每类用户的平均访问次数。
    在这里插入图片描述

2.4 分析

在这里插入图片描述

2.5 实现

with t1 as (selectuser_id, user_type, visit_count,ntile(10) over (order by visit_count desc) as ntfrom user_visits
)
selectuser_type,round(avg(visit_count), 1) as avg_visit
from t1
where t1.nt>2
group by user_type
order by user_type;

3. 前百分之N的问题 百分比 PERCENT_RANK

3.1 语法

PERCENT_RANK() 是 SQL 中的窗口函数,用于计算某行的百分比排名。这个函数在数据分析中常用于了解某一数据点在整体数据中的相对位置。百分比排名的取值范围是从 0 到 1,表示当前行在分区内的排名相对于分区内其他行的百分比位置。

PERCENT_RANK() OVER (PARTITION BY column ORDER BY column)
  • PARTITION BY column:可选,用于按指定列对数据进行分区。
  • ORDER BY column:必需,用于指定每个分区内的排序。
    PERCENT_RANK() 的计算方式是:
百分比排名 = (当前行的排名 - 1) / (分区内的行总数 - 1)

3.1.1 示例

假设我们有一个包含学生成绩的表 students_score,结构如下:
在这里插入图片描述
计算每个学生的百分比排名。

SELECTstudent_id,name,score,PERCENT_RANK() OVER (ORDER BY score DESC) as `percent_rank`
FROMstudents_score;

结果
在这里插入图片描述

3.1.2 注意事项

  • 排序顺序:PERCENT_RANK() 的计算依赖于 ORDER BY 子句指定的排序顺序。在上面的例子中,我们按照 score 降序排列,最高分的学生的 percent_rank 是 0。

  • 分区:如果使用了 PARTITION BY 子句,则 PERCENT_RANK() 会在每个分区内计算百分比排名,而不是在整个结果集上。

  • 相同值:在处理相同值时,PERCENT_RANK() 会为相同值分配相同的排名百分比。

  • 第一行和最后一行:第一行的 percent_rank 总是 0,而最后一行的 percent_rank 总是 1。

PERCENT_RANK() 常用于了解数据在分布中的相对位置,对于生成百分比排名或分位数分析非常有用。

3.2 需求

  • 用户访问次数表,包含用户编号、用户类型、访问次数。
  • 要求在剔除访问次数前20%的用户后得到每类用户的平均访问次数。
    在这里插入图片描述

3.3 实现

with t1 as (selectuser_id, user_type, visit_count,percent_rank() over (order by visit_count desc) as prfrom user_visits
)
selectuser_type,round(avg(visit_count), 1) as avg_visit
from t1
where pr>0.2
group by user_type
order by user_type;

4. 偏移函数: 求环比增长率

4.1 需求

假设有一个销售数据表 sales,其中记录了每个月的销售额,想要计算每个月的销售额与上个月的销售额之间的变化。
在这里插入图片描述

4.2 语法

LAG() 是 SQL 中的一个窗口函数,用于从当前行向上偏移指定数量的行,并返回偏移行的值。它对于访问前面的行数据而不使用自连接非常有用,特别是在时间序列数据和累积计算中。

LAG(column, offset, default) OVER (PARTITION BY partition_column ORDER BY order_column)

参数解释:
参数解释

  • column: 这是你要获取前值的列。
  • offset: 向上偏移的行数。默认为1,表示返回前一行的值。
  • default: 当偏移行超出窗口范围时返回的默认值。如果没有指定,默认值为 NULL。
  • PARTITION BY partition_column: 可选项,用于指定分区列。在每个分区内独立计算 LAG 值。如果没有指定,整个结果集将视为一个分区。
  • ORDER BY order_column: 必需项,用于指定窗口函数处理数据的顺序。

4.3 示例

假设有一个包含月份销售数据的表 monthly_sales,其结构如下:
在这里插入图片描述
获取每个月的销售额,以及与前一个月销售额的差异。

SELECTmonth,sales,LAG(sales, 1) OVER (ORDER BY month) AS previous_sales,LAG(sales, 1, 666) OVER (ORDER BY month) AS previous_sales_2
FROM sales_data;

结果:
在这里插入图片描述

4.4 解释

  • LAG(sales, 1, 0) OVER (ORDER BY month): 该表达式获取前一个月的销售额。如果没有前一个月的数据(例如对于第一行),则返回默认值 0。
  • sales - previous_sales: 计算当前月与上月的销售额差异。

4.5 分析

在这里插入图片描述

4.6 实现

drop database if exists db_1;
create database db_1;
use db_1;-- 创建表
CREATE TABLE sales_data (month VARCHAR(7) NOT NULL,sales INT NOT NULL,PRIMARY KEY (month)
);-- 插入数据
INSERT INTO sales_data (month, sales) VALUES
('2023-01', 1000),
('2023-02', 1100),
('2023-03', 1050),
('2023-04', 1200),
('2023-05', 1150);select * from sales_data;# 目标: 求环比增长率 = (当前月销量 - 上一月销量) / 上一月销量 * 100
selectmonth,sales,lag(sales, 1, 0) over(order by month) as lag_1_sales,# sales - (lag(sales, 1) over(order by month)) as diff,# (sales - (lag(sales, 1) over(order by month))) / (lag(sales, 1) over(order by month)) * 100 as rate,# round((sales - (lag(sales, 1) over(order by month))) / (lag(sales, 1) over(order by month)) * 100, 2) as rate_2,concat(round((sales - (lag(sales, 1) over(order by month))) / (lag(sales, 1) over(order by month)) * 100, 1), '%') as rate_3
from sales_data;

4.6 总结

- LAG(字段, [N], [M]):返回分区中当前行前第N行的指定字段的内容,如果没有,默认返回M
- LEAD(字段, [N], [M]):返回分区中当前行后第N行的指定字段的内容,如果没有,默认返回M

  • first_val(…)
  • last_val(…)
  • 注意:M和N可以省略,N默认为1,M默认为NULL。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 图的拓扑排序
  • RabbitMQ如何保证可靠性
  • 文档控件DevExpress Office File API v24.1 - 支持基于Unix系统的打印
  • 正则表达式扩展应用
  • Linux/C 高级——shell脚本
  • elasticsearch教程
  • 学习记录——day28 信号量集
  • 未来展望:PLC远程控制网关与工业物联网融合的发展趋势
  • 【Linux】系列入门摘抄笔记-4-查看文件内容命令cat/more/less/tail
  • web基础与http协议与配置
  • 美的神机后续
  • 【Datawhale AI夏令营第四期】 Datawhale AI夏令营第四期 魔搭-AIGC方向 Task01笔记
  • Android 文件上传与下载
  • 引导过程与服务控制
  • springbootAl农作物病虫害预警系统-计算机毕业设计源码21875
  • SegmentFault for Android 3.0 发布
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Laravel核心解读--Facades
  • linux安装openssl、swoole等扩展的具体步骤
  • Rancher如何对接Ceph-RBD块存储
  • SpiderData 2019年2月25日 DApp数据排行榜
  • Vue 动态创建 component
  • 讲清楚之javascript作用域
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 字符串匹配基础上
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​zookeeper集群配置与启动
  • # 安徽锐锋科技IDMS系统简介
  • #### golang中【堆】的使用及底层 ####
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (1)SpringCloud 整合Python
  • (2022 CVPR) Unbiased Teacher v2
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (二)WCF的Binding模型
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (六)Flink 窗口计算
  • (万字长文)Spring的核心知识尽揽其中
  • (译)计算距离、方位和更多经纬度之间的点
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .aanva
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .Net Core 中间件与过滤器
  • .Net 代码性能 - (1)
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .NET序列化 serializable,反序列化
  • .Net中的设计模式——Factory Method模式
  • @modelattribute注解用postman测试怎么传参_接口测试之问题挖掘
  • @PreAuthorize与@Secured注解的区别是什么?
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [2009][note]构成理想导体超材料的有源THz欺骗表面等离子激元开关——