sql题之使用dense_rank,row_number,collect_set,later view explode解决最近日期信息的问题

从订单信息表(order_info)中查询出每个用户的最近三个下单日期的所有订单

需要用到的表:

订单信息表:order_info

order_id (订单id) user_id (用户id) create_date (下单日期) total_amount (订单金额)
1 101 2021-09-30 29000.00
10 103 2020-10-02 28000.00

期望如下结果:

user_id <string> order_id <string> create_date <string>
101 2 2021-09-28
101 3 2021-09-29
101 4 2021-09-30
102 5 2021-10-01
102 6 2021-10-01
102 8 2021-10-02
103 9 2021-10-02
103 10 2021-10-02
103 12 2021-10-03
104 13 2021-10-03
104 14 2021-10-03
104 15 2021-10-03
105 17 2021-10-04
105 18 2021-10-04
105 19 2021-10-04
106 22 2021-10-05
106 23 2021-10-05
106 24 2021-10-05
107 25 2021-10-05
107 27 2021-10-06
107 28 2021-10-06
108 29 2021-10-06
108 31 2021-10-07
108 32 2021-10-07
109 33 2021-10-07
109 35 2021-10-08
109 36 2021-10-08
1010 37 2021-10-08
1010 38 2021-10-08
1010 39 2020-10-08

---总结,本题有三种做法,

1.使用dense_rank排名密集排名,按照用户分区日期排序,日期相同则排名相同,取排名1,2,3的所有信息即为最近三日的所有下单信息
sql 复制代码
select user_id, order_id,create_date
from ( select user_id , order_id, create_date,
       dense_rank()over (partition by user_id order by create_date desc) rk
       from order_info
     ) t1
where rk <= 3
2.使用collect_set获取所有的订单集合,然后使用later view explode炸裂集合,非常巧妙的把同一天的下单日期按照日期使用row_number排名之后再展开
sql 复制代码
select
    user_id,
    create_date,
    order_id
from(
    select
        user_id,
        collect_set(order_id) orders,
        create_date,
        row_number() over (partition by user_id order by create_date desc) rn
    from order_info
    group by create_date, user_id
)t lateral view explode(orders) tmp as order_id 
where rn <= 3;
在当前写法中,某大佬使用了group by 和 partition by 同时结合在一起使用的方法,首先是

用group by 进行分组,然后collect_set形成集合,同时在对用户分区日期排名取排名。 之后便是对集合展开,从而获取排名中所有的日期的订单信息。

3.使用row_number排名获取排名日期,同时关联原表获取所有下单信息。
sql 复制代码
select
  t2.user_id,
  order_id,
  t2.create_date
from
  (
    select
      user_id,
      create_date
    from
      (
        select
          user_id,
          create_date,
          row_number() over (
            partition by
              user_id
            order by
              create_date desc
          ) rn
        from
          order_info
        group by
          user_id,
          create_date
      ) t1
    where
      rn <= 3
  ) t2
  join order_info oi on t2.user_id = oi.user_id
  and t2.create_da
相关推荐
卿雪2 小时前
Redis 线程模型:Redis为什么这么快?Redis为什么引入多线程?
java·数据库·redis·sql·mysql·缓存·golang
QQ 19226384 小时前
采用整数规划的光储调度:光伏储能优化调度探究
sql
l1t5 小时前
利用Duckdb求解Advent of Code 2025第5题 自助餐厅
数据库·sql·mysql·算法·oracle·duckdb·advent of code
驾数者5 小时前
Flink SQL关联查询:双流Join与维表Join实战技巧
数据库·sql·flink
白衣衬衫 两袖清风6 小时前
SQL索引优化
数据库·sql
Hello.Reader8 小时前
在 Flink SQL 中玩转实时模型推理 —— ML_PREDICT 实战解析
sql·flink·linq
Hello.Reader9 小时前
Flink SQL 窗口表值函数TUMBLE / HOP / CUMULATE / SESSION
java·sql·flink
Franciz小测测10 小时前
Python APScheduler 定时任务 独立调度系统设计与实现
java·数据库·sql
少年攻城狮1 天前
Mybatis-Plus系列---【自定义拦截器实现sql完整拼接及耗时打印】
数据库·sql·mybatis
迷茫的21世纪的新轻年1 天前
PostgreSQL——SQL优化
数据库·sql·postgresql