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
相关推荐
geNE GENT13 小时前
SQL 中UPDATE 和 DELETE 语句的深入理解与应用
数据库·sql
dLYG DUMS14 小时前
如何在docker中的mysql容器内执行命令与执行SQL文件
sql·mysql·docker
以神为界14 小时前
PHP与数据库交互实操:连接方法+SQL注入防范+系统数据库解析
数据库·sql·网络安全·php·web
auspicious航14 小时前
PostgreSQL性能优化实战——索引、SQL与参数调优
sql·postgresql·性能优化
cyber_两只龙宝15 小时前
【Oracle】Oracle之SQL的集合运算符
linux·运维·数据库·sql·云原生·oracle
若兰幽竹16 小时前
【从零开始编写数据库系统:架构设计与实现】第3章 SQL解析:词法与语法分析
数据库·sql·教学数据库·数据库内核开发
geBR OTTE16 小时前
开源的Text-to-SQL工具WrenAI
数据库·sql·开源
Deitymoon17 小时前
嵌入式数据库——API创建
数据库·sql
NaMM CHIN1 天前
sql实战解析-sum()over(partition by xx order by xx)
数据库·sql
不瘦80斤不改名1 天前
深入浅出 MySQL(一):一文理清 SQL 核心规范与五大分类
数据库·sql·mysql