MySQL(六) 窗口函数的四种应用场景介绍

在SQL中,窗口函数的出现使得实现分组查询变得便捷,今天,总结四种窗口函数的应用场景。

目录

      • 一、查询组内第N项记录
      • 二、查询不同种类下数量前N的记录
      • 三、查询前20%的记录
      • 四、查询连续登录天数为7天的记录

一、查询组内第N项记录

某店铺现有交易数据表goods_sale_table如下:

goods_id 商品ID
goods_type 商品类型
goods_sales 商品销量

现想了解每种产品类型销量前2名的商品
输出要求如下:

  • goods_id 商品id (销量排名前2名)
  • goods_type 商品种类

1、数据准备

CREATE TABLE goods_sale_table ( goods_id INT, goods_type VARCHAR ( 10 ), goods_sale INT );
INSERT INTO goods_sale_table
VALUES
	( 1, '电脑数码', 400 ),
	( 2, '家用电器', 600 ),
	( 3, '电脑数码', 500 ),
	( 4, '游戏', 550 ),
	( 5, '家用电器', 1000 ),
	( 6, '电脑数码', 1200 ),
	( 7, '游戏', 700 ),
	( 8, '游戏', 750 ),
	( 9, '家用电器', 1100 ),
	( 10, '电脑数码', 900 );

2、完整查询代码

SELECT
	a.goods_id,
	a.goods_type 
FROM
	( SELECT goods_id, goods_type, row_number ( ) over ( PARTITION BY goods_type ORDER BY goods_sale DESC ) AS ranking FROM goods_sale_table ) a 
WHERE
	a.ranking <= 2;

MySQL(六) 窗口函数的四种应用场景介绍_第1张图片

二、查询不同种类下数量前N的记录

某班现有如下成绩表course_table如下:

id 学号
grade 年级
course 课程

现想了解每个年级最受欢迎的两门课程
输出要求如下:

  • grade (年级)
  • course (最受欢迎的两门课程)

1、数据准备

CREATE TABLE course_table ( id INT, grade VARCHAR ( 10 ), course VARCHAR ( 10 ) );
INSERT INTO course_table;
VALUES
(1,'一年级','心理学'),(2,'二年级','社会学'),(3,'三年级','社会学'),(4,'一年级','刑侦学'),(5,'二年级','心理学'),
(6,'三年级','计算机'),(7,'一年级','刑侦学'),(8,'二年级','心理学'),(9,'三年级','社会学'),(10,'一年级','社会学'),
(11,'二年级','社会学'),(12,'二年级','计算机'),(13,'一年级','心理学'),(14,'三年级','刑侦学'),(15,'三年级','计算机');

2、完整代码

SELECT
	t2.grade,
	t2.course 
FROM
	(
SELECT
	grade,
	course,
	row_number ( ) over ( PARTITION BY grade ORDER BY stu_num DESC ) AS ranking 
FROM
	( SELECT grade, course, count( id ) as stu_num FROM course_table GROUP BY grade, course ) t1 
	) t2 
WHERE t2.ranking <3;

MySQL(六) 窗口函数的四种应用场景介绍_第2张图片

三、查询前20%的记录

某支付平台现有交易数据表user_sales_table如下:

user_name 用户名
pay_amount 用户支付额度

现想了解支付金额在前20%的用户
输出要求如下:

  • user_name 用户名(前20%的用户)

1、数据准备

CREATE TABLE user_sales_table ( user_name VARCHAR ( 10 ), pay_amount INT );
INSERT INTO user_sales_table
VALUES
	('A',50),('A',100),('B',250),('B',20),('B',30),
	('C',100),('C',180),('D',120),('D',25),('E',408),
	('F',162),('F',327),('F',198),('F',195),('G',372),
	('G',291),('G',347),('G',207),('G',412),('H',234),
	('H',404),('I',377),('I',295),('I',374),('J',311);

部分数据如下
MySQL(六) 窗口函数的四种应用场景介绍_第3张图片
2、完整查询代码
思路:利用ntile函数按照各用户的支付总额度将其分为五组,则排名第一组的则是前20%的用户

SELECT
	a.user_name 
FROM
	( SELECT user_name, ntile ( 5 ) over ( ORDER BY sum( pay_amount ) DESC ) AS ranking FROM user_sales_table GROUP BY user_name ) a 
WHERE
	a.ranking = 1;

MySQL(六) 窗口函数的四种应用场景介绍_第4张图片

四、查询连续登录天数为7天的记录

某游戏平台现有用户登录表user_login_table如下:

user_name 用户名
date 用户登录时间

现想了解连续7天都登录平台的重要用户
输出要求如下:

  • user_name 用户名(连续七天都登录的用户)

1、数据准备

CREATE TABLE user_login_table ( user_name VARCHAR ( 5 ), date VARCHAR ( 10 ) );
INSERT INTO user_login_table
VALUES
	('A','2020/8/1'),('B','2020/8/2'),('A','2020/8/2'),('C','2020/8/3'),
	('A','2020/8/3'),('D','2020/8/4'),('C','2020/8/4'),('B','2020/8/4'),
	('A','2020/8/4'),('A','2020/8/5'),('B','2020/8/5'),('C','2020/8/6'),
	('A','2020/8/6'),('A','2020/8/7'),('A','2020/8/8'),('B','2020/8/9');

2、完整查询代码
思路:首先,利用lead函数查询每个用户后7条记录,如果有则返回相应日期,如果无则返回NULL;其次,查询用户登录时间往后推七天的日期

注意:用户的下一条记录不一定是连续登录的日期!

SELECT
	user_name 
FROM
	( SELECT user_name, date, lead ( date, 7 ) over ( PARTITION BY user_name ) AS date_7 FROM user_login_table ) a 
WHERE
	a.date_7 IS NOT NULL 
	AND date_add(date, interval 7 day) = cast(date_7 as date)

MySQL(六) 窗口函数的四种应用场景介绍_第5张图片

你可能感兴趣的:(MySQL,mysql,sql,数据库)