Как я могу написать запрос, чтобы получить число вхождений каждого календарного месяца в диапазоне дат - PullRequest
0 голосов
/ 12 июля 2019

У меня есть таблица со столбцами «start_date» и «end_date», и я пытаюсь суммировать даты, разбивая их по периоду.Например, если начальная и конечная даты равны '01 -JAN-2017 'и '01 -MAR-2018' соответственно, то запрос должен возвращать каждый месяц в виде различных полей / столбцов.Кроме того, я хочу видеть число появлений / происшествий, сделанных каждым месяцем в течение периода, т.е. месяцы, такие как JAN, FEB и MAR, должны иметь значение 2, поскольку они произошли дважды в течение периода между «01-январь-2017» и «01-MAR-2018 '.

например, если 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 голосов
/ 12 июля 2019

В приведенном ниже решении даты range_start и range_end жестко закодированы в предложении with (подзапрос). Вы можете изменить их, например, для привязки переменных, чтобы разрешить ввод данных пользователем.

В основном запросе я обычно создаю небольшую таблицу со значениями от 1 до 12 (запрос connect by) и использую оператор 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
0 голосов
/ 12 июля 2019

Это должно помочь вам начать. Это был пример, который я должен был сделать, чтобы разделить время регистрации и выезда сотрудников по дням, но концепция похожа. Мы синтезируем промежуточные данные, а затем поворачиваемся в строки

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>
...