多个州之间的天数差异

Posted

技术标签:

【中文标题】多个州之间的天数差异【英文标题】:Difference in days between multiple states 【发布时间】:2018-07-30 14:28:34 【问题描述】:

我正在使用 ORACLE SQL,但遇到了一个难以解决的问题。

在我的系统中用户可以订购产品。这些订单可以处于不同的状态:WAITINGACCEPTEDIN_PROGRESSDELIVEREDREMOVEDDELETED。 这些订单记录在一个名为 tblorderlog 的表中。

该表包含以下列:OrderIdOrderStateOrderStateDate

我想找出OrderStateDates 之间的天数差异,但问题是并非每个订单都经过每个订单状态,因此一个订单可能只来自WAITINGDELIVEREDREMOVED。 无论州的顺序如何,有没有办法计算州之间的天数?

我做了什么:

select distinct susu.orderid, ol.orderstatedate,  ol.orderstate,
case
when ol.orderstate =  'WAITING' then null 
when ol.orderstate =  'ACCEPTED' then round(tblaccepted.orderstatedate- 
tblwaiting,0)
when ol.orderstate =  'IN_PROGRESS' then round(tblinprogress.orderstatedate-tblaccepted.orderstatedate,0)
when ol.orderstate = 'DELIVERED' then round(tbldelivered.orderstatedate-tblinprogress.orderstatedate,0)
when ol.orderstate =  'REMOVED' then round(tblremoved.orderstatedate-tbldelivered.orderstatedate,0)
when ol.orderstate = 'DELETED' then round(tbldeleted.orderstatedate-tblremoved.orderstatedate,0)
else -10 --(Random number)
end as days_between_orderstates
from tblsusu susu
left join tblorderlog ol on susu.orderid = ol.orderid
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'WAITING') tblwaiting on susu.orderid = tblwaiting.orderid 
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'ACCEPTED') tblaccepted on susu.orderid = tblaccepted.orderid 
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'IN_PROGRESS') tblinprogress on susu.orderid = tblinprogress.orderid 
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'DELIVERED') tbldelivered on susu.orderid = tbldelivered.orderid 
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'REMOVED') tblremoved on susu.orderid = tblremoved.orderid 
left join (select ol.orderid, ol.orderstatedate
       from tblorderlog ol
       where ol.orderstate = 'DELETED') tbldeleted on susu.orderid = tbldeleted.orderid 
order by susu.orderid, ol.orderstatedate

我想要这样的输出:

orderid    orderstate        orderdate     days_between_order_states
21          WAITING          22/07/18              NULL (or empty)
21          ACCPETED         24/07/18              2
21          DELIVERED        25/07/18              1
21          REMOVED          25/07/18              0
21          DELETED          26/07/18              1
25          WAITING          01/08/18              NULL (or empty)
25          DELIVERED        05/08/18              4
25          DELETED          06/08/18              1
..
..

【问题讨论】:

状态可以按任何顺序排列,不只是有些可以跳过?它们可以重复吗?请在您的问题中包含一些具有代表性的示例数据和预期结果(作为格式化文本,而不是图像)。 您绝对不需要对同一个表 (tblorderlog) 进行那么多左连接,只需添加一个,在您的案例表达式中,您可以将其别名与 orderstate 列一起使用。 @JorgeCampos,你能举个例子吗? 当您按照@AlexPoole 的要求在问题中添加信息时,我可以。 @AlexPoole 感谢您的编辑,我在这里有点新。但这是预期的输出 【参考方案1】:

如果您真的只是在寻找每个订单状态以及自前一个状态以来的天数,不管是什么,那么您并没有真正关注每个状态值 - 您只关注状态更改的顺序。

您可以使用lag() 分析函数来查看前一行,您可以在其中定义over() 子句中“上一个”的含义;在这里,您需要具有最近状态更改日期的相同订单 ID 的行。

作为起点,您可以查看以下内容:

select susu.orderid, ol.orderstatedate, ol.orderstate,
  lag(ol.orderstatedate)
    over (partition by susu.orderid order by ol.orderstatedate) as prev_orderstatedate,
  lag(ol.orderstate)
    over (partition by susu.orderid order by ol.orderstatedate) as prev_orderstate,
  round(ol.orderstatedate - lag(ol.orderstatedate)
    over (partition by susu.orderid order by ol.orderstatedate))
    as days_between_orderstates
from tblsusu susu
join tblorderlog ol on ol.orderid = susu.orderid
order by susu.orderid, ol.orderstatedate;

对于每个订单日志条目,它将显示该状态及其日期;以及通过lag() 找到的先前状态和日期;并将计算当前时间和以前时间之间的差异。

根据您添加到问题的输出,并从中推断出原始数据并作为两个 CTE 提供(并跳过您不想要的 prev_ 值):

with tblsusu (orderid) as (
            select 21 from dual
  union all select 25 from dual
), tblorderlog (orderid, orderstate, orderstatedate) as (
            select 21, 'WAITING', date '2018-07-22' from dual
  union all select 21, 'ACCPETED', date '2018-07-24' from dual
  union all select 21, 'DELIVERED', date '2018-07-25' from dual
  union all select 21, 'REMOVED', date '2018-07-25' from dual
  union all select 21, 'DELETED', date '2018-07-26' from dual
  union all select 25, 'WAITING', date '2018-08-01' from dual
  union all select 25, 'DELIVERED', date '2018-08-05' from dual
  union all select 25, 'DELETED', date '2018-08-06' from dual
)
select susu.orderid, ol.orderstatedate, ol.orderstate,
  round(ol.orderstatedate - lag(ol.orderstatedate)
    over (partition by susu.orderid order by ol.orderstatedate))
    as days_between_orderstates
from tblsusu susu
join tblorderlog ol on ol.orderid = susu.orderid
order by susu.orderid, ol.orderstatedate;

   ORDERID ORDERSTATE ORDERSTATE DAYS_BETWEEN_ORDERSTATES
---------- ---------- ---------- ------------------------
        21 2018-07-22 WAITING                            
        21 2018-07-24 ACCPETED                          2
        21 2018-07-25 DELIVERED                         1
        21 2018-07-25 REMOVED                           0
        21 2018-07-26 DELETED                           1
        25 2018-08-01 WAITING                            
        25 2018-08-05 DELIVERED                         4
        25 2018-08-06 DELETED                           1

如果除了来自tblsusu 的订单 ID 之外,您没有获得任何列,您甚至可能不需要表之间的连接,因为无论如何这在两个表中都存在。

【讨论】:

以上是关于多个州之间的天数差异的主要内容,如果未能解决你的问题,请参考以下文章

两个日期之间的天数差异[重复]

如何使用javascript查找两个日期之间的天数差异

如何计算不同时区的两个 NSDate 对象之间的天数差异?

如何获取 MySQL 上两个日期之间的差异天数?

2 个时间戳之间的 SQL Redshift 天数差异

试图在Python中找到用户出生日期和现在之间的天数差异