【问题标题】:How to count the number of entries between a time period如何计算一个时间段之间的条目数
【发布时间】:2019-12-03 02:32:59
【问题描述】:

我在下面有一个示例表,其中显示了票号、票的打开时间和关闭时间。

TKTNUM  OPEN_DATE           CLOSE_DATE
1234    12-Mar-19 08:36     14-Mar-19 08:36
1235    13-Mar-19 08:36     15-Mar-19 08:36
1236    14-Mar-19 08:36     16-Mar-19 08:36
1237    15-Mar-19 08:36 
1238    16-Mar-19 08:36 
1239    17-Mar-19 08:36 
1240    18-Mar-19 08:36     20-Mar-19 08:36
1241    19-Mar-19 08:36     20-Mar-19 08:36
1242    20-Mar-19 08:36     21-Mar-19 08:36

我需要计算一天的开/关票数...

DATE                OPEN        CLOSED
12-Mar-19 08:36     1           0
13-Mar-19 08:36     2           0
14-Mar-19 08:36     2           1
15-Mar-19 08:36     2           2
16-Mar-19 08:36     2           3
17-Mar-19 08:36     3           3
18-Mar-19 08:36     4           3
19-Mar-19 08:36     5           3
20-Mar-19 08:36     4           5

非常感谢任何帮助。谢谢


在示例 job_history 表上使用了下面的查询(c/o Tejash)

EMPLOYEE_ID START_DATE           END_DATE             JOB_ID     DEPARTMENT_ID
----------- -------------------- -------------------- ---------- -------------
        200 17/SEP/1995 00:00:00 17/JUN/2001 00:00:00 AD_ASST               90
        101 21/SEP/1997 00:00:00 27/OCT/2001 00:00:00 AC_ACCOUNT           110
        102 13/JAN/2001 00:00:00 24/JUL/2006 00:00:00 IT_PROG               60
        101 28/OCT/2001 00:00:00 15/MAR/2005 00:00:00 AC_MGR               110
        200 01/JUL/2002 00:00:00 31/DEC/2006 00:00:00 AC_ACCOUNT            90
        201 17/FEB/2004 00:00:00 19/DEC/2007 00:00:00 MK_REP                20
        114 24/MAR/2006 00:00:00 31/DEC/2007 00:00:00 ST_CLERK              50
        176 24/MAR/2006 00:00:00 31/DEC/2006 00:00:00 SA_REP                80
        176 01/JAN/2007 00:00:00 31/DEC/2007 00:00:00 SA_MAN                80
        122 01/JAN/2007 00:00:00 31/DEC/2007 00:00:00 ST_CLERK              50

With dates(dt)
As (Select mindt + level - 1 from
        (Select min(start_date) mindt, max(end_date) maxdt from job_history)
      Connect by level <= maxdt - mindt + 1)
Select dt, 
       sum(case when dt between start_date and coalesce(end_date,dt) then 1 end) as startdate, 
       Sum(case when dt >= end_date then 1 end) as enddate
From dates cross join job_history
Group by dt 
Order by dt desc

2001 年 6 月 17 日,查询给出了

DT                    STARTDATE    ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00          3         10
<SNIPPED>
17/JUN/2001 00:00:00          3          1

代替

DT                    STARTDATE    ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00          3         10
<SNIPPED>
17/JUN/2001 00:00:00          2          1

试图编辑查询,现在它给了我

DT                    STARTDATE    ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00             <<<    10   
<snipped>
18/JUN/2001 00:00:00          2          1
17/JUN/2001 00:00:00          2  <<<     1   
16/JUN/2001 00:00:00          3          1

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    您可以使用日期作为总天数的 cte,然后将其再次加入同一张表,如下所示:

    With dates(dt)
    As
    (
    Select mindt + level - 1 from
      (Select min(open_date) mindt, max(open_dt) maxdt from your_table)
    Connect by level <= maxdt - mindt + 1
    )
    Select dt, 
           sum(case when dt between open_date and coalesce(close_date,dt) then 1 end) as open, 
           Sum(case when dt >= close_date then 1 end) as closed
    From dates cross join your_table
    Group by dt;
    

    干杯!!

    【讨论】:

      【解决方案2】:

      您可以取消透视和聚合:

      select dte, sum(is_open) as num_opens, sum(is_close) as num_closes
      from ((select open_date as dte, 1 as is_open, 0 as is_close
             from t
            ) union all
            (select close_date, 0 as is_open, 1 as is_close
             from t
            ) 
           ) t
      group by dte
      order by dte;
      

      注意:截断日期可能是个好主意,这样它就没有时间组件:

      select trunc(dte), sum(is_open) as num_opens, sum(is_close) as num_closes
      from ((select open_date as dte, 1 as is_open, 0 as is_close
             from t
            ) union all
            (select close_date, 0 as is_open, 1 as is_close
             from t
            ) 
           ) t
      where dte is not null
      group by trunc(dte)
      order by trunc(dte);
      

      在 Oracle 12C 中,您可以为此使用横向 join

      select trunc(dte), sum(is_open), sum(is_close)
      from t cross join lateral
           (select t.open_date as dte, 1 as is_open, 0 as is_close from dual union all
            select t.close_date, 0 as is_open, 1 as is_close from dual
           ) t
      group by trunc(dte)
      order by trunc(dte);
      

      【讨论】:

        猜你喜欢
        • 2018-10-16
        • 1970-01-01
        • 1970-01-01
        • 2017-06-06
        • 1970-01-01
        • 1970-01-01
        • 2017-10-29
        • 2022-09-27
        • 1970-01-01
        相关资源
        最近更新 更多