MySQL中最新订单状态的SQL查询

Posted

技术标签:

【中文标题】MySQL中最新订单状态的SQL查询【英文标题】:SQL query for latest Order Status in MySQL 【发布时间】:2021-05-13 06:03:58 【问题描述】:

我们正在跟踪我们的运输合作伙伴通过他们触发的 webhook 发送的订单状态。 Webhook 每次触发时都会添加一行,因此每个订单都有多行与之关联。

表的结构 enter image description here

我们正在尝试创建一个 sql 查询以获取以下内容

查找最后收到的“awb”行。获取该行中的 current_status。如果current_status 是“PICKUP EXCEPTION”、“OUT FOR PICKUP”、“PICKUP RESCHEDULED”中的任何一个,则找到该特定“awb”的这些状态第一次出现的行 检查 awb 的这些状态第一次出现和最后一次出现之间的天数 并输出相差超过 2 天的 awb。

这是我能够创建的查询。

WITH ranked_order_status AS (
  SELECT os.*,
   datediff(
   now() ,
   first_value(recived_at) over (partition by awb order by recived_at asc)
  ) as diff,  
  ROW_NUMBER() OVER (PARTITION BY awb ORDER BY recived_at desc) AS rn
  FROM order_status AS os where  current_status in ('PICKUP EXCEPTION', 'OUT FOR PICKUP', 'PICKUP RESCHEDULED')
)
SELECT * FROM ranked_order_status WHERE rn = 1 and diff > 2 

不幸的是,这向我显示了所有具有这些状态的行的 awb,而不仅仅是那些最后收到的当前状态为“PICKUP EXCEPTION”、“OUT FOR PICKUP”、“PICKUP RESCHEDULED”的awb

知道如何编辑吗?

【问题讨论】:

如果不包括示例数据,您可能无法得到答案。 @TimBiegeleisen 在此处添加示例数据的最佳方式是什么?我有 .sql 文件。而且它不是太大。截至目前 5000 行 你可以使用db-fiddle.com 【参考方案1】:

所以如果我理解正确的话,这应该是一个使用 RANK() 的分析函数的明确案例。

这将是我对您提到的约束的方法:

WITH t1 AS (
  SELECT 
    os.*, 
    FIRST_VALUE(os.received_at) OVER(PARTITION BY os.awb ORDER BY os.received_at) AS first_received_at
  FROM order_status AS os 
  WHERE os.current_status IN ('PICKUP EXCEPTION', 'OUT FOR PICKUP', 'PICKUP RESCHEDULED')
),
t2 AS (
  SELECT 
    RANK() OVER (PARTITION BY t1.awb ORDER BY t1.received_at DESC) AS reverse_event_sequence,
    DATE_DIFF(t1.received_at, t1.first_received_at, DAY) AS day_diff
    t1.*
  FROM t1
),
final AS (
  SELECT * 
  FROM t2
  WHERE t2.day_diff > 2 AND t2.reverse_event_sequence = 1
)
SELECT * FROM final

基本上,您希望首先获取每行的 received_at 的第一个值,然后您希望对每个 awb 的所有事件进行排名并按降序排列以始终将最后一个事件作为 rank=1,然后您对日期差异应用所需的约束:)

我不得不提一下,没有数据样本也无济于事。并且希望对我的方法有任何反馈:)

【讨论】:

忘了提到函数的语法可能会有所不同(例如 date_diff()),因为我是在 StandardSQL 而不是 mysql 上编写的。很抱歉! 排名将是一个不错的选择。会试试这个。 嗨@lenoldvaz 你终于发现它有用了吗?想知道:D【参考方案2】:

您可以通过两种方式从最近的行中枚举行:

按 awb 分区,按接收顺序降序 按 awb 和状态分区,并按收到的降序排序

对于每个 awb 的最后状态,它们之间的差异将为零。你可以选择这个然后聚合:

select awb, current_status,
       min(received_at), max(received_at)
from (select os.*,
             row_number() over (partition by awb order by received_at desc) as seqnum,
             row_number() over (partition by awb, current_status order by received_at desc) as seqnum_2
      from order_status os
     ) os
where seqnum = seqnum_2 and
      current_status in ('PICKUP EXCEPTION', 'OUT FOR PICKUP', 'PICKUP RESCHEDULED')
group by awb, current_status
having max(received_at) > min(received_at) + interval 2 day;

【讨论】:

以上是关于MySQL中最新订单状态的SQL查询的主要内容,如果未能解决你的问题,请参考以下文章

sql查询平均下单时间

一次动态sql查询订单数据的设计

SQL的一些查询语句

Sql 查询以获取最多 10 条的最新记录并按提到行排名的字段排序 [关闭]

sql查询以下内容

一个事务中多条查询sql是取最新数据吗