先看题目自己试着解一下,有困难的同学可以先看考点解析试下,
最后再看SQL解答,有不同意见和解法的欢迎评论区留言交流
来源:大厂面试真题
题目:
【1】现有交易数据明细表 user_goods_table 如下:
user_name 用户名
date 下单日期
city_name 下单所在城市
order_number 订单号
goods_kind 用户订购的的外卖品类
sku_id 用户购买的商品
ID sku_name 用户购买的商品名称 num 数量
请按以下要求编写SQL查询:
- 近 7 天,每天各城市总单量
- 近 7 天,每天各城市的单量在全国总单量中的占比,结果以百分比显示保留两位小数
- 近 7 天,上海市每日单量和累计单量
- 拉取近 7 天,每天各城市总单量的排名
- 近 7 天上海市,每个用户购买最多的外卖品类分别是哪个 。输出要求如下: user_name 用户名 goods_kind 该用户购买的最多外卖品类
user_name | date | day_num | city_name | order_number | goods_kind | sku_id | sku_name | num |
---|---|---|---|---|---|---|---|---|
A001 | 2023/7/3 0:00 | 0 | 北京 | '1003887892136 | A | '74696815 | 随机1 | 1 |
A002 | 2023/7/2 0:00 | 1 | 北京 | '1005064667309 | B | '45694701 | 随机9 | 3 |
A003 | 2023/7/1 0:00 | 2 | 上海 | '1009389809705 | A | '58585992 | 随机1 | 2 |
A004 | 2023/6/30 0:00 | 3 | 深圳 | '1008250650306 | C | '50432693 | 随机2 | 3 |
A005 | 2023/6/29 0:00 | 4 | 杭州 | '1009977503419 | D | '49481095 | 随机3 | 4 |
A006 | 2023/6/28 0:00 | 5 | 上海 | '1007870492015 | B | '44044231 | 随机6 | 1 |
A007 | 2023/6/27 0:00 | 6 | 南京 | '1005278176195 | E | '78072661 | 随机7 | 2 |
A008 | 2023/6/26 0:00 | 7 | 北京 | '1004993853535 | A | '21327409 | 随机8 | 4 |
A009 | 2023/6/25 0:00 | 8 | 上海 | '1002658059711 | F | '40984501 | 随机9 | 3 |
A010 | 2023/6/24 0:00 | 9 | 北京 | '1007862991739 | A | '53306964 | 随机1 | 3 |
A011 | 2023/6/23 0:00 | 10 | 北京 | '1009176079538 | B | '35126040 | 随机2 | 1 |
A012 | 2023/6/22 0:00 | 11 | 上海 | '1003283849139 | A | '75512162 | 随机3 | 5 |
A001 | 2023/6/21 0:00 | 12 | 深圳 | '1005309121451 | C | '16972175 | 随机4 | 2 |
A002 | 2023/7/3 0:00 | 0 | 杭州 | '1008432457883 | D | '40643753 | 随机5 | 3 |
A003 | 2023/7/3 0:00 | 0 | 上海 | '1006219163729 | B | '46484869 | 随机6 | 2 |
A004 | 2023/7/2 0:00 | 1 | 广州 | '1001344025562 | E | '37473733 | 随机7 | 3 |
A005 | 2023/7/1 0:00 | 2 | 北京 | '1002080528170 | A | '66382803 | 随机8 | 2 |
A006 | 2023/6/30 0:00 | 3 | 上海 | '1001794915821 | F | '11932822 | 随机9 | 4 |
A001 | 2023/7/3 0:00 | 0 | 北京 | '1007408706780 | A | '32988274 | 随机3 | 4 |
A002 | 2023/7/2 0:00 | 1 | 北京 | '1005769283808 | B | '65429791 | 随机4 | 2 |
A003 | 2023/7/1 0:00 | 2 | 上海 | '1007434060136 | A | '73899401 | 随机5 | 1 |
A004 | 2023/6/30 0:00 | 3 | 深圳 | '1002842229878 | C | '46885196 | 随机5 | 4 |
A005 | 2023/6/29 0:00 | 4 | 杭州 | '1007076524029 | D | '34396380 | 随机4 | 3 |
A006 | 2023/6/28 0:00 | 5 | 上海 | '1008068624085 | B | '60142654 | 随机5 | 5 |
A007 | 2023/6/27 0:00 | 6 | 南京 | '1001965114347 | E | '10507129 | 随机5 | 1 |
A008 | 2023/6/26 0:00 | 7 | 北京 | '1001916308114 | A | '27310633 | 随机6 | 1 |
A009 | 2023/6/25 0:00 | 8 | 上海 | '1005935754286 | F | '80570037 | 随机7 | 1 |
A010 | 2023/6/24 0:00 | 9 | 北京 | '1002273475054 | A | '38987004 | 随机8 | 4 |
A011 | 2023/6/23 0:00 | 10 | 北京 | '1005729675662 | B | '66338170 | 随机7 | 3 |
A012 | 2023/6/22 0:00 | 11 | 上海 | '1005046041350 | A | '47768813 | 随机8 | 2 |
A001 | 2023/6/21 0:00 | 12 | 深圳 | '1003795764689 | C | '90967505 | 随机9 | 4 |
A002 | 2023/7/3 0:00 | 0 | 杭州 | '1001569464839 | D | '45301007 | 随机2 | 4 |
A003 | 2023/7/3 0:00 | 0 | 上海 | '1005321717416 | B | '41454673 | 随机7 | 1 |
A004 | 2023/7/2 0:00 | 1 | 广州 | '1005128597676 | E | '59339022 | 随机8 | 4 |
A005 | 2023/7/1 0:00 | 2 | 北京 | '1006325509528 | A | '86094427 | 随机9 | 3 |
A006 | 2023/6/30 0:00 | 3 | 上海 | '1004855507423 | F | '13034047 | 随机1 | 4 |
结果输出
Q1执行结果
Q2执行结果
Q3执行结果
Q4执行结果
Q5执行结果
考点解析
Q1:
逻辑口述:
date_sub+curdate 计算出七天前的日期(注意含不含今天),使用between and 筛选出符合日期的数据, 再对筛选结果 用group by 聚合+对order_num 用count 计数
主要考点:
日期计算:date_sub
当前日期:curdate
分组统计:group by + count
Q2:
逻辑口述:
针对Q1筛选出来的数据,不聚合,使用开窗count() over()把聚合后的结果分列在每一行,一个按city_name聚合,一个不聚合(得到的就是全国的订单总量),把两个数据相除得到占比,在外面嵌套distinct去重即可
考察点:
count,max,sum 开窗与不开窗的区别
with as 创建中间表
Q3:
逻辑口述:
针对给定条件筛选出来的数据,
使用count() over 开窗函数进行累计
考察点:
Q4:
逻辑口述:
考察点: row_number, rank, dense_rank 排序的窗口函数
Q5:
逻辑口述:
考察点: row_number, rank, dense_rank 排序的窗口函数
SQL代码
--Q1
SELECT city_name,count(order_number) total_order FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()
group by city_name;
--Q2
# 方法一 开窗函数:
select distinct city_name, concat(round(percent*100,2),"%") city_percent
from (
SELECT *,
count(order_number) over(partition by city_name)
/count(order_number) over() percent
FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()) tmp;
# 方法二:
with tmp as (SELECT
city_name,
count(order_number) city_order
FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()
group by city_name )
select city_name, city_order/sum(city_order) over() from tmp;
-- select city_name, city_order/(select sum(city_order) from tmp) from tmp ;
-- 总计行的计算
--SELECT
-- COALESCE(city_name,"总计") city_name,
-- count(order_number) city_order
-- FROM ` user_goods_table`
-- where `date` between date_sub(curdate(),interval 6 day) and curdate()
-- group by city_name
-- with rollup;
--Q3
-- SQL关键词执行顺序,group by 在select 之前执行
--partition by 和group by不能一起使用,重复分组了,先group by 再 partition by
SELECT
distinct city_name,
date_format(`date`,"%Y-%m-%d") `date`,
count(order_number)over( partition by `date`) orders_day,
count(order_number)over(order by `date`) cum_orders_day
FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()
and city_name = "上海"
--Q4
-- 使用 num 商品数量计算,数据为自主生成,order_num count 每天都是2,排名都是1,看不出来排差异
select *,
dense_rank()over(partition by city_name order by city_orders_d ) `rank` from (
SELECT
city_name,
date_format(`date`,"%Y-%m-%d") `date`,
sum(num) city_orders_d
FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()
group by city_name,`date`) tmp
--Q5
select user_name, goods_kind from (
select *,
rank() over(partition by user_name order by nums_user) rk from (
SELECT
user_name,
goods_kind,
sum(num) nums_user
FROM ` user_goods_table`
where `date` between date_sub(curdate(),interval 6 day) and curdate()
group by user_name,goods_kind) tmp) t2
where rk = 1