我正在使用ORACLE SQL,遇到一个问题,我很难解决。
在我的系统中,用户可以订购产品。这些顺序可以处于不同的状态:WAITING
,ACCEPTED
,IN_PROGRESS
,DELIVERED
,REMOVED
,DELETED
。
这些订单记录在名为tblorderlog的表中。
该表包含以下列:OrderId
,OrderState
和OrderStateDate
。
我想找出OrderStateDates
之间的天数差异,但是问题在于并非每个订单都经过每个订单状态,因此一个订单可能仅来自WAITING
,DELIVERED
和REMOVED
。
无论州的顺序如何,有没有一种方法可以计算州之间的日期?
我做了什么:
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
..
..
答案 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之外没有其他任何列,则甚至不需要在表之间进行联接,因为无论如何这两个表中都存在。