多个州之间的天数差异

时间:2018-07-30 14:28:34

标签: sql oracle

我正在使用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
..
..

1 个答案:

答案 0 :(得分:4)

如果您实际上只是在寻找每个订单状态以及自上一个状态以来的天数(无论是什么天),那么您实际上就不会关注每个状态值,而只会关注状态更改的顺序。

您可以使用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之外没有其他任何列,则甚至不需要在表之间进行联接,因为无论如何这两个表中都存在。