求解
【类型】:聚合窗口函数高级用法
【场景】:近几日的数据情况 【分类】:高级聚合窗口函数—窗口函数的移动平均
分析思路
难点:
1.当有2个变量时如何处理:使用高级窗口函数或者笛卡尔积
(1)统计订单完成记录和取消记录
加时间限制条件是为了减少计算量
-
[条件] 国庆头3天里近7日的时间范围
-
[使用] group by dt_7
(2)统计国庆头3天里,每天的近7日日均订单完成量和日均订单取消量,按日期升序排序。结果保留2位小数
- [使用] avg(finish_cut) over(order by dt_7 rows 6 preceding)
- 或者 sum(finish_cut) over(order by dt_7 rows 6 preceding)/7
求解代码
方法一
with子句
with
main as(
#统计订单完成记录和取消记录(加时间限制是为了减少计算量)
select
date(finish_time) as dt_7,
count(if(start_time is not null,order_id,null)) as finish_cut,
count(if(start_time is null,order_id,null)) as cancel_cut
from tb_get_car_order
where date(finish_time) between '2021-09-25' and '2021-10-03'
group by dt_7
order by dt_7 desc
)
#统计国庆头3天里,每天的近7日日均订单完成量和日均订单取消量,按日期升序排序。结果保留2位小数
select distinct
dt_7 as dt,
round(avg(finish_cut) over(order by dt_7 rows 6 preceding),2) as finish_num_7d,
round(avg(cancel_cut) over(order by dt_7 rows 6 preceding),2) as cancel_num_7d
from main
order by dt_7
limit 6,3
统计订单完成记录和取消记录输出
1 2021-10-03|1|1
2 2021-10-02|3|1
3 2021-10-01|2|0
4 2021-09-30|2|0
5 2021-09-29|1|0
6 2021-09-28|1|0
7 2021-09-27|1|0
8 2021-09-26|1|1
9 2021-09-25|2|0
每天的近7日日均订单完成量和日均订单取消量输出
1 2021-09-25|0.29|0.00
2 2021-09-26|0.43|0.14
3 2021-09-27|0.57|0.14
4 2021-09-28|0.71|0.14
5 2021-09-29|0.86|0.14
6 2021-09-30|1.14|0.14
7 2021-10-01|1.43|0.14
8 2021-10-02|1.57|0.29
9 2021-10-03|1.57|0.29
最后利用 limit 6,3 取国庆头3天。
方法二
from子查询
#统计国庆头3天里,每天的近7日日均订单完成量和日均订单取消量,按日期升序排序。结果保留2位小数
select distinct
dt_7 as dt,
round(sum(finish_cut) over(order by dt_7 rows 6 preceding)/7,2) as finish_num_7d,
round(sum(cancel_cut) over(order by dt_7 rows 6 preceding)/7,2) as cancel_num_7d
from(
#统计订单完成记录和取消记录(加时间限制是为了减少计算量)
select
date(finish_time) as dt_7,
count(if(start_time is not null,order_id,null)) as finish_cut,
count(if(start_time is null,order_id,null)) as cancel_cut
from tb_get_car_order
where date(finish_time) between '2021-09-25' and '2021-10-03'
group by dt_7
order by dt_7 desc
) main
order by dt_7
limit 6,3
方法三
不使用窗口函数 使用union连接所有行
优点:思路清晰、暴力破解
缺点:当求的天数变多或者有些天数不需要计算近7日的信息时,会出现计算代码繁杂和不能计算的情况
with
main as(
#统计订单完成记录和取消记录(加时间限制是为了减少计算量)
select
date(finish_time) as dt_7,
count(if(start_time is not null,order_id,null)) as finish_cut,
count(if(start_time is null,order_id,null)) as cancel_cut
from tb_get_car_order
where date(finish_time) between '2021-09-25' and '2021-10-03'
group by dt_7
order by dt_7 desc
)
,attr as(
#统计国庆第一天近7日日均订单完成量和日均订单取消量
select
'2021-10-01' as dt,
round(sum(if(datediff('2021-10-01',dt_7) between 0 and 6,finish_cut,0))/7,2) as finish_num_7d,
round(sum(if(datediff('2021-10-01',dt_7) between 0 and 6,cancel_cut,0))/7,2) as cancel_num_7d
from main
)
,attr1 as(
#统计国庆第二天近7日日均订单完成量和日均订单取消量
select
'2021-10-02' as dt,
round(sum(if(datediff('2021-10-02',dt_7) between 0 and 6,finish_cut,0))/7,2) as finish_num_7d,
round(sum(if(datediff('2021-10-02',dt_7) between 0 and 6,cancel_cut,0))/7,2) as cancel_num_7d
from main
)
,attr2 as(
#统计国庆第三天近7日日均订单完成量和日均订单取消量
select
'2021-10-03' as dt,
round(sum(if(datediff('2021-10-03',dt_7) between 0 and 6,finish_cut,0))/7,2) as finish_num_7d,
round(sum(if(datediff('2021-10-03',dt_7) between 0 and 6,cancel_cut,0))/7,2) as cancel_num_7d
from main
)
#统计国庆头3天里,每天的近7日日均订单完成量和日均订单取消量,按日期升序排序。结果保留2位小数
select *
from attr
union
select *
from attr1
union
select *
from attr2
方法四
不使用窗口函数 做笛卡尔积后查找近7日数据做处理
优点:当求的天数变多或者有些天数不需要计算近7日的信息时,也可以计算
with
main as(
#统计订单完成记录和取消记录(加时间限制是为了减少计算量)
select
date(finish_time) as dt_7,
count(if(start_time is not null,order_id,null)) as finish_cut,
count(if(start_time is null,order_id,null)) as cancel_cut
from tb_get_car_order
where date(finish_time) between '2021-09-25' and '2021-10-03'
group by dt_7
order by dt_7 desc
)
,attr as(
#得到国庆头三天日期(为了分别计算每个日期的近7日数据,先要得到头三天的日期)
select distinct
date(finish_time) as dt
from tb_get_car_order
where date(finish_time) between '2021-10-01' and '2021-10-03'
)
#统计国庆头3天里,每天的近7日日均订单完成量和日均订单取消量,按日期升序排序。结果保留2位小数
select
dt,
round(sum(if(datediff(dt,dt_7) between 0 and 6,finish_cut,0))/7,2) as finish_num_7d,
round(sum(if(datediff(dt,dt_7) between 0 and 6,cancel_cut,0))/7,2) as cancel_num_7d
from main,attr
group by dt
order by dt