SQL / PLSQL查询以获取开始日期和结束日期之间的差额之和

时间:2019-11-25 11:23:23

标签: sql oracle plsql

我有一个包含以下数据的表

Date_from     Date_to
20-NOV-19     22-NOV-19
10-NOV-19     21-NOV-19
14-NOV-19     26-NOV-19

我需要查询以查找date_from和date_to之间的差之和。

示例 19年11月20日和19年11月22日之间的差异为 2天 19年11月10日与19年11月21日之间的差值为11天,但查询必须将其视为 9天,因为第一行已考虑20天11月,21天11月。 19-Nov-19和26-Nov-19之间的区别是12天,但查询必须将其视为 4天 因为上面的行中已经考虑了11月14日至11月22日。

查询结果应为15天(2 + 9 + 4)。

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:0)

另一个变体:

with t as (
select to_date('20-11-2019','DD.MM.YYYY') Date_from,to_date('22-11-2019','DD.MM.YYYY') Date_to from dual
union all
select to_date('10-11-2019','DD.MM.YYYY') Date_from,to_date('21-11-2019','DD.MM.YYYY') Date_to from dual
union all
select to_date('14-11-2019','DD.MM.YYYY') Date_from,to_date('26-11-2019','DD.MM.YYYY') Date_to from dual
),
alldays as
(select (select min(t.Date_from) from t)+level-1 dt  from dual connect by level<(select max(t.Date_to)+2 from t)-(select min(t.Date_from) from t))
select count(distinct a.dt)-1 from t
join alldays a on a.dt>=t.Date_from  and a.dt<t.Date_to
order by a.dt    

答案 1 :(得分:0)

这里是一个选择:内联视图获取CFROMCTO之间的所有日期,并返回不同日期的数量。

SQL> WITH test (cfrom, cto)
  2       -- sample data
  3       AS (SELECT DATE '2019-11-20', DATE '2019-11-22' FROM DUAL
  4           UNION ALL
  5           SELECT DATE '2019-11-10', DATE '2019-11-21' FROM DUAL
  6           UNION ALL
  7           SELECT DATE '2019-11-14', DATE '2019-11-26' FROM DUAL)
  8  -- this is useful code
  9  SELECT COUNT (DISTINCT datum) - 1 diff
 10    FROM (SELECT cfrom + COLUMN_VALUE - 1 datum
 11            FROM test
 12                 CROSS JOIN
 13                 TABLE (
 14                    CAST (
 15                       MULTISET (    SELECT LEVEL
 16                                       FROM DUAL
 17                                 CONNECT BY LEVEL <= cto - cfrom) AS SYS.odcinumberlist)));

      DIFF
----------
        15

SQL>

答案 2 :(得分:0)

这是间隙和孤岛问题的一种变体。

这是方法:

  • 使用lag()或累积最大值来确定新时期的起点(“岛屿”)。
  • 使用起点以累积起点总数来标识岛屿。
  • 聚集岛屿。
  • 总体汇总。

所以:

select sum(date_to - date_from)
from (select min(date_from) as date_from, max(date_to) as date_to
      from (select t.*,
                   sum(case when prev_dt >= date_from then 0 else 1 end) over (order by date_from) as grp
            from (select t.*,
                         lag(date_to) over (order by date_from) as prev_dt
                  from t
                 ) t
           ) t
      group by grp
     ) t;

答案 3 :(得分:-1)

std::string