如何在sql中减去两列的日期

时间:2016-10-22 19:18:26

标签: sql oracle select plsql

请浏览此编辑的表格。

enter image description here

您可以将order_header_key视为订单号

我想获取当前状态为3且先前状态为2的订单号列表,以及该订单的状态日期(status3) - 状态日期(2)<= 3天

在下表中 对于订单no-1'日期(状态3)' - '日期(状态2)= 20 OCT - 19 OCT 这不到3天 - &gt;如此有效的订单

但是对于订单号3'日期(状态3)' - '日期(状态2)'= 30 OCT - 24 OCT 这超过3天所以无效订单

订单号为2无效,因为状态为3和1,2,缺少

3 个答案:

答案 0 :(得分:3)

假设订单每个order_no / status组合不能有多个条目,您可以加入两个子查询:

SELECT s3.order_no
FROM   (SELECT *
        FROM   orders
        WHERE  status = 3) s3
JOIN   (SELECT *
        FROM   orders
        WHERE  status = 2) s2 ON s3.order_no = s2.order_no AND 
                                 s3.status_date - s3.status_date <= 3

答案 1 :(得分:3)

使用lag()

select o.*
from (select o.*,
             lag(o.status_date) over (partition by o.order_no order by o.status_date ) as prev_sd,
             lag(o.status) over (partition by o.order_no order by o.status_date) as prev_status
      from orders o
     ) o
where prev_status = 2 and status = 3 and
      (status_date - prev_sd) <= 3;

答案 2 :(得分:2)

分析函数(在这种情况下为lag())允许您避免连接和/或子查询,并且可能(通常会)更快。

with
--   begin test data; not part of the solution
     orders ( order_no, status, status_date ) as (
       select 1, 1, to_date('18-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 2, to_date('19-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 3, to_date('20-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 1, to_date('20-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 3, to_date('23-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 2, to_date('24-OCT-16', 'DD-MON-YY')from dual union all
       select 1, 1, to_date('30-OCT-16', 'DD-MON-YY')from dual       
     ),
--   end test data; solution is the word "with" from above, plus the query below     
     prep ( order_no, status, status_date, prev_status, prev_status_date) as (
       select order_no, status, status_date,
              lag(status) over (partition by order_no order by status_date),
              lag(status_date) over (partition by order_no order by status_date)
       from   orders
     )
select order_no
from   prep
where  status = 3 and prev_status = 2 and prev_status_date - status_date <= 3
;


ORDER_NO
--------
       1