Сводка: создать столбец для записи повторяющихся дат цикла - PullRequest
0 голосов
/ 27 марта 2019

У меня есть таблицы ниже.Соединение из цикла в программу основано на дате.Существуют миллионы записей PGMID, поэтому я думал о функции поворота, но я не могу жестко закодировать PGMID.Любые мысли / помощь будут оценены.У меня есть возможность редактировать таблицы в БД.

Таблица: цикл

 ID     START_CYCLE END_CYCLE
 4400   7/22/2018   8/3/2018
 4400   8/4/2018    8/5/2018
 4400   8/6/2018    8/6/2018
 4400   8/7/2018    8/9/2018
 4400   8/10/2018   9/6/2018
 4400   9/7/2018    9/7/2018
 4400   9/8/2018    9/9/2018
 4400   9/10/2018   12/31/9999     

Таблица: программа

PGMID  START_DT    END_DT
 101    8/4/2018   9/10/2018
 102    9/8/2018   9/8/2018
 103    9/10/2018  NULL

Вывод:

 ID   START_CYCLE   END_CYCLE  PGMID       
 4400  7/22/2018    8/3/2018     
 4400   8/4/2018    8/5/2018    101
 4400   8/6/2018    8/6/2018    101
 4400   8/7/2018    8/9/2018    101
 4400   8/10/2018   9/6/2018    101
 4400   9/7/2018    9/7/2018    101
 4400   9/8/2018    9/9/2018    101
 4400   9/8/2018    9/9/2018    102
 4400   9/10/2018   12/31/9999  103

Есть повторяющиеся записи цикла, я НЕхочу какие-нибудь повторные даты.

 4400   9/8/2018    9/9/2018    101
 4400   9/8/2018    9/9/2018    102

Ожидаемый результат:

 ID   START_CYCLE   END_CYCLE  PROGRAM1  PROGRAM2       
 4400  7/22/2018    8/3/2018     
 4400   8/4/2018    8/5/2018    101
 4400   8/6/2018    8/6/2018    101
 4400   8/7/2018    8/9/2018    101
 4400   8/10/2018   9/6/2018    101
 4400   9/7/2018    9/7/2018    101
 4400   9/8/2018    9/9/2018    101      102
 4400   9/10/2018   12/31/9999  103

Ответы [ 2 ]

3 голосов
/ 03 апреля 2019
select * 
  from (
    select id, start_cycle, end_cycle, pgmid, case when rn > 5 then 0 else rn end rn
      from (
        select id, start_cycle, end_cycle, pgmid, 
               row_number() over (partition by id, start_cycle, end_cycle order by pgmid) rn
          from cycle c
          left join program p on p.start_dt <= c.end_cycle and c.start_cycle <= p.end_dt ))
  pivot (listagg(pgmid, ',') within group (order by pgmid) 
         for rn in (1 program1, 2 program2, 3 program3, 4 program4, 5 program5, 0 others))
  order by id, start_cycle
  • данные о левом соединении, как вы сделали,
  • добавить row_number (), разбитый на каждый цикл и упорядоченный по pgmid,
  • , если это число превышает некоторое число (в моем случае это 5), затем присвойте 0 вместо этого
  • make pivot, используя этот столбец.Первые пять столбцов построены как всегда, последний, который может содержать больше программ, называется others
  • вместо обычно используемых в сводной таблице min или max use listagg

Эти шаги были необходимы, чтобы показать все программы, если их более 5 в цикле.Все остальные в others.Если вы знаете, что может быть не более, скажем, 3 программы, то вы можете упростить этот запрос.

Если вы хотите, чтобы каждая программа в отдельном столбце и число максимальных столбцов было неизвестно, то это проблема динамического поворота.На Stack Overflow уже описаны некоторые решения, но в основном это обходные пути.

Вот пример, где у нас есть до 8 программ в одном цикле:

with 
  cycle(id, start_cycle, end_cycle) as (
    select 4400, date '2018-07-22', date '2018-08-03' from dual union all
    select 4400, date '2018-08-04', date '2018-08-05' from dual union all
    select 4400, date '2018-08-06', date '2018-08-06' from dual union all
    select 4400, date '2018-08-07', date '2018-08-09' from dual union all
    select 4400, date '2018-08-10', date '2018-09-06' from dual union all
    select 4400, date '2018-09-07', date '2018-09-07' from dual union all
    select 4400, date '2018-09-08', date '2018-09-09' from dual union all
    select 4400, date '2018-09-10', date '9999-12-31' from dual ), 
  program(pgmid, start_dt, end_dt) as (
    select 101, date '2018-08-04', date '2018-09-10' from dual union all
    select 104, date '2018-08-06', date '2018-08-07' from dual union all
    select 105, date '2018-08-06', date '2018-08-07' from dual union all
    select 106, date '2018-08-06', date '2018-08-07' from dual union all
    select 107, date '2018-08-06', date '2018-08-07' from dual union all
    select 108, date '2018-08-06', date '2018-08-07' from dual union all
    select 109, date '2018-08-06', date '2018-08-07' from dual union all
    select 110, date '2018-08-07', date '2018-08-07' from dual union all
    select 102, date '2018-09-08', date '2018-09-08' from dual union all
    select 103, date '2018-09-10', null  from dual )
select * 
  from (
    select id, start_cycle, end_cycle, pgmid, case when rn > 5 then 0 else rn end rn
      from (
        select id, start_cycle, end_cycle, pgmid, 
               row_number() over (partition by id, start_cycle, end_cycle order by pgmid) rn
          from cycle c
          left join program p on p.start_dt <= c.end_cycle and c.start_cycle <= p.end_dt ))
  pivot (listagg(pgmid, ',') within group (order by pgmid) 
         for rn in (1 program1, 2 program2, 3 program3, 4 program4, 5 program5, 0 others))
  order by id, start_cycle

Результат:

    ID START_CYCLE END_CYCLE   PROGRAM1  PROGRAM2  PROGRAM3  PROGRAM4  PROGRAM5  OTHERS
 ----- ----------- ----------- --------- --------- --------- --------- --------- ------------
  4400 2018-07-22  2018-08-03                                                    
  4400 2018-08-04  2018-08-05  101                                               
  4400 2018-08-06  2018-08-06  101       104       105       106       107       108,109
  4400 2018-08-07  2018-08-09  101       104       105       106       107       108,109,110
  4400 2018-08-10  2018-09-06  101                                               
  4400 2018-09-07  2018-09-07  101                                               
  4400 2018-09-08  2018-09-09  101       102                                     
  4400 2018-09-10  9999-12-31  101                                               

Демоверсия dbfiddle

0 голосов
/ 01 апреля 2019

1 - Вы должны добавить "group by START_CYCLE, END_CYCLE" 2- В выбранном разделе необходимо добавить group_concat (разделитель PGMID ',')

Я не знаю оракула для выше, но в MySQL это:

select ..., group_concat(PGMID separator ',') as PGMIDs, ... 
from ... 
join ... 
where ... 
group by START_CYCLE, END_CYCLE 

Я надеюсь помочь вам.

...