如何编写查询以获取日期范围内每个日历月的出现次数

时间:2019-07-11 22:58:38

标签: sql oracle oracle11gr2

我有一个表,该表的列为“ start_date”和“ end_date”,我试图通过在整个期间内划分日期来总结日期。例如,如果开始日期和结束日期分别为“ 01-JAN-2017”和“ 01-MAR-2018”,则查询应将每个月作为不同的字段/列返回。另外,我想查看此期间每个月出现的次数/发生次数,即JAN,FEB和MAR等月份的值应为2,因为它们在“ 01-JAN-2017”和“ 2018年3月1日”。

例如,如果start_date = '01 -JAN-2018'和end_date = '31 -MAR-2019',则输出应为:

 jan | feb | mar | apr | may | jun | jul | aug | sep | oct | nov | dec
-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----
   2 |   2 |   2 |   1 |   1 |   1 |   1 |   1 |   1 |   1 |   1 |   1

2 个答案:

答案 0 :(得分:0)

这应该使您入门。这是我必须做的一个示例,用于将员工的登记入住和退房时间划分为一天,但是这个概念是相似的。我们合成中间数据,然后转到行中

SQL> create table t
  2  ( emp int,
  3    in_time date,
  4    out_time date );

Table created.

SQL>
SQL>
SQL> insert into t values (1, trunc(sysdate)+1.5/24,   trunc(sysdate)+3.5/24);

1 row created.

SQL> insert into t values (1, trunc(sysdate)+5.4/24,   trunc(sysdate)+9.5/24);

1 row created.

SQL> insert into t values (1, trunc(sysdate)+10/24,   trunc(sysdate)+11/24);

1 row created.

SQL>
SQL> insert into t values (2, trunc(sysdate)+2.2/24,   trunc(sysdate)+3.5/24);

1 row created.

SQL> insert into t values (2, trunc(sysdate)+5/24,   trunc(sysdate)+7/24);

1 row created.

SQL> insert into t values (2, trunc(sysdate)+10.7/24,   trunc(sysdate)+11.2/24);

1 row created.

SQL> insert into t values (2, trunc(sysdate)+9.2/24,   trunc(sysdate)+9.4/24);

1 row created.

SQL>
SQL> @longdate

Session altered.

SQL>
SQL> select
  2       emp,
  3       in_time,
  4       out_time,
  5       to_number(to_char(in_time,'HH24')) as in_hr,
  6       to_number(to_char(out_time,'HH24')) as out_hr,
  7       to_number(to_char(in_time,'MI')) as in_min,
  8       to_number(to_char(out_time,'MI')) as out_min
  9    from t;

       EMP IN_TIME             OUT_TIME                 IN_HR     OUT_HR     IN_MIN    OUT_MIN
---------- ------------------- ------------------- ---------- ---------- ---------- ----------
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          1          3         30         30
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          5          9         24         30
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         10         11          0          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          2          3         12         30
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          5          7          0          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         10         11         42         12
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          9          9         12         24

7 rows selected.

SQL>
SQL> with t_extended as
  2  ( select
  3       emp,
  4       in_time,
  5       out_time,
  6       to_number(to_char(in_time,'HH24')) as in_hr,
  7       to_number(to_char(out_time,'HH24')) as out_hr,
  8       to_number(to_char(in_time,'MI')) as in_min,
  9       to_number(to_char(out_time,'MI')) as out_min
 10    from t
 11  ),
 12  hr_of_day as
 13    ( select level-1 hr from dual connect by level <= 24 )
 14  select
 15    e.emp,
 16    e.in_time,
 17    e.out_time,
 18    h.hr,
 19    case
 20      -- totally outside range
 21      when in_hr > hr then 0
 22      when out_hr < hr then 0
 23      -- less than 1 hour
 24      when in_hr = hr and out_hr = hr then  out_min - in_min
 25      -- ends on hour
 26      when in_hr < hr and out_hr = hr then  out_min
 27      -- start on hour
 28      when in_hr = hr and out_hr > hr then 60 - in_min
 29      -- contained
 30      when in_hr < hr and out_hr > hr then 60
 31    end dur
 32  from t_extended e, hr_of_day h
 33  order by 1,2,4;

       EMP IN_TIME             OUT_TIME                    HR        DUR
---------- ------------------- ------------------- ---------- ----------
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          0          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          1         30
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          2         60
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          3         30
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          4          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          5          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          6          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          7          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          8          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00          9          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         10          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         11          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         12          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         13          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         14          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         15          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         16          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         17          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         18          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         19          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         20          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         21          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         22          0
         1 12/07/2019 01:30:00 12/07/2019 03:30:00         23          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          0          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          1          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          2          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          3          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          4          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          5         36
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          6         60
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          7         60
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          8         60
         1 12/07/2019 05:24:00 12/07/2019 09:30:00          9         30
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         10          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         11          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         12          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         13          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         14          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         15          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         16          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         17          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         18          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         19          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         20          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         21          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         22          0
         1 12/07/2019 05:24:00 12/07/2019 09:30:00         23          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          0          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          1          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          2          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          3          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          4          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          5          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          6          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          7          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          8          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00          9          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         10         60
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         11          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         12          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         13          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         14          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         15          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         16          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         17          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         18          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         19          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         20          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         21          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         22          0
         1 12/07/2019 10:00:00 12/07/2019 11:00:00         23          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          0          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          1          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          2         48
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          3         30
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          4          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          5          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          6          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          7          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          8          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00          9          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         10          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         11          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         12          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         13          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         14          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         15          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         16          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         17          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         18          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         19          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         20          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         21          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         22          0
         2 12/07/2019 02:12:00 12/07/2019 03:30:00         23          0

       EMP IN_TIME             OUT_TIME                    HR        DUR
---------- ------------------- ------------------- ---------- ----------
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          0          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          1          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          2          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          3          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          4          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          5         60
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          6         60
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          7          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          8          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00          9          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         10          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         11          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         12          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         13          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         14          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         15          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         16          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         17          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         18          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         19          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         20          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         21          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         22          0
         2 12/07/2019 05:00:00 12/07/2019 07:00:00         23          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          0          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          1          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          2          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          3          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          4          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          5          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          6          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          7          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          8          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00          9         12
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         10          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         11          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         12          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         13          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         14          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         15          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         16          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         17          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         18          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         19          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         20          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         21          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         22          0
         2 12/07/2019 09:12:00 12/07/2019 09:24:00         23          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          0          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          1          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          2          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          3          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          4          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          5          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          6          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          7          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          8          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00          9          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         10         18
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         11         12
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         12          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         13          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         14          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         15          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         16          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         17          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         18          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         19          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         20          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         21          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         22          0
         2 12/07/2019 10:42:00 12/07/2019 11:12:00         23          0

168 rows selected.

SQL>
SQL> with t_extended as
  2  ( select
  3       emp,
  4       in_time,
  5       out_time,
  6       to_number(to_char(in_time,'HH24')) as in_hr,
  7       to_number(to_char(out_time,'HH24')) as out_hr,
  8       to_number(to_char(in_time,'MI')) as in_min,
  9       to_number(to_char(out_time,'MI')) as out_min
 10    from t
 11  ),
 12  hr_of_day as
 13    ( select level-1 hr from dual connect by level <= 24 ),
 14  raw_data as (
 15  select
 16    e.emp,
 17    e.in_time,
 18    e.out_time,
 19    h.hr,
 20    case
 21      -- totally outside range
 22      when in_hr > hr then 0
 23      when out_hr < hr then 0
 24      -- less than 1 hour
 25      when in_hr = hr and out_hr = hr then  out_min - in_min
 26      -- ends on hour
 27      when in_hr < hr and out_hr = hr then  out_min
 28      -- start on hour
 29      when in_hr = hr and out_hr > hr then 60 - in_min
 30      -- contained
 31      when in_hr < hr and out_hr > hr then 60
 32    end dur
 33  from t_extended e, hr_of_day h
 34  --order by 1,2,4
 35  )
 36  select *
 37  from  ( select emp, hr, dur from raw_data )
 38  pivot ( sum(dur) as t for (hr) in ( 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23))
 39  /

       EMP        0_T        1_T        2_T        3_T        4_T        5_T        6_T        7_T        8_T        9_T
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
      10_T       11_T       12_T       13_T       14_T       15_T       16_T       17_T       18_T       19_T       20_T
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
      21_T       22_T       23_T
---------- ---------- ----------
         1          0         30         60         30          0         36         60         60         60         30
        60          0          0          0          0          0          0          0          0          0          0
         0          0          0

         2          0          0         48         30          0         60         60          0          0         12
        18         12          0          0          0          0          0          0          0          0          0
         0          0          0


SQL>
SQL>

答案 1 :(得分:0)

在下面的解决方案中,range_start和range_end日期被硬编码在with子句(子查询)中。您可以更改这些值,例如绑定变量,以允许用户输入。

在主查询中,按照通常的方式(一个connect by查询)创建一个值从1到12的小表,并使用pivot运算符将结果对齐一行pivot是Oracle 11.1中引入的,因此您很可能可以使用它,但是如果您的版本较旧,则存在其他透视方法,同样可以很好地发挥作用。

解决方案的核心是pivot的第一部分中的数学计算。我不会在这里解释数学(如果不是很清楚),因为这是一个编程论坛,而不是算术论坛。

with
  test_data as (
    select to_date('01-JAN-2017', 'dd-MON-yyyy') as range_start,
           to_date('31-MAR-2018', 'dd-MON-yyyy') as range_end
    from   dual
  )
select *
from   (select level as mth from dual connect by level <= 12) 
       cross join test_data
pivot  (min(extract(year from range_end) - extract(year from range_start) + 1
            - case when extract(month from range_start) > mth then 1 else 0 end
            - case when extract(month from range_end)   < mth then 1 else 0 end)
        for mth in (1 jan, 2 feb, 3 mar, 4 apr, 5 may, 6 jun, 7 jul, 8 aug, 9 sep,
                          10 oct, 11 nov, 12 dec))
;

输出

JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
--- --- --- --- --- --- --- --- --- --- --- ---
  2   2   2   1   1   1   1   1   1   1   1   1