在SQL中,窗口函数的出现使得实现分组查询变得便捷,今天,总结四种窗口函数的应用场景。
某店铺现有交易数据表goods_sale_table如下:
goods_id | 商品ID |
---|---|
goods_type | 商品类型 |
goods_sales | 商品销量 |
现想了解每种产品类型销量前2名的商品
输出要求如下:
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;
某班现有如下成绩表course_table如下:
id | 学号 |
---|---|
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;
某支付平台现有交易数据表user_sales_table如下:
user_name | 用户名 |
---|---|
pay_amount | 用户支付额度 |
现想了解支付金额在前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);
部分数据如下
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;
某游戏平台现有用户登录表user_login_table如下:
user_name | 用户名 |
---|---|
date | 用户登录时间 |
现想了解连续7天都登录平台的重要用户
输出要求如下:
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)