【问题标题】:How to subtract dates of two column in sql如何在sql中减去两列的日期
【发布时间】:2017-03-04 21:54:22
【问题描述】:

请浏览这个编辑过的表格。

您可以假设 order_header_key 为订单号。

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

在下表中 对于订单号 1 '日期(状态 3)' - '日期(状态 2)= 10 月 20 日 - 10 月 19 日 不到 3 天--> 如此有效的订单

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

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

【问题讨论】:

    标签: sql oracle select plsql


    【解决方案1】:

    假设一个订单的每个 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 号订单的状态为 18 日创建的订单,然后下订单19日发货,20日发货
    【解决方案2】:

    使用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;
    

    【讨论】:

    • order bylag() 的解析子句中是强制性的(出于明显的逻辑原因和语法规则要求);没有它,查询将无法编译。
    • @mathguy 。 . .谢谢。我只是不小心把它漏掉了。
    • 一个小问题,如果我想获取其他两种状态(比如状态 3 和状态 1)之间的日期差异,我该怎么做?
    • 因为使用了lag order by,所以只能获取上一条记录,如何具体选择满足一定条件的记录呢?就我而言,我想获取他们的状态记录
    • @NagarajB 。 . .这是一个非常不同的问题,应该单独提出。这个问题很清楚地是关于在状态 2 记录之后的状态 3 记录。您需要非常清楚这些状态是否可以重复并包含适当的示例数据。
    【解决方案3】:

    分析函数(在这种情况下为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
    

    【讨论】:

      猜你喜欢
      • 2014-06-24
      • 2016-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多