powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / задачка с запросом
2 сообщений из 2, страница 1 из 1
задачка с запросом
    #39586941
gda
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
drop table aaa;
create table aaa (date_from date, date_to date, c1 integer, c2 integer, c3 integer);
drop table bbb;
create table bbb (date_from date, date_to date, c4 integer, c5 integer, c6 integer);
insert into aaa values (to_date('20010101','YYYYMMDD'),to_date('20010331','YYYYMMDD'),1,0,0);
insert into aaa values (to_date('20030601','YYYYMMDD'),to_date('20041231','YYYYMMDD'),7,0,3);
insert into aaa values (to_date('20080101','YYYYMMDD'),null,1,8,0);
insert into bbb values (to_date('20020101','YYYYMMDD'),to_date('20020731','YYYYMMDD'),1,0,0);
insert into bbb values (to_date('20030101','YYYYMMDD'),to_date('20040131','YYYYMMDD'),1,0,7);
insert into bbb values (to_date('20060101','YYYYMMDD'),null,1,0,4);
commit;



Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
Data from aaa
1. 01/01/2001  31/03/2001  1   0   0
2. 01/06/2003  31/12/2004  7   0   3
3. 01/01/2008              1   8   0

Data from bbb
1. 01/01/2002  31/07/2002  1   0   0
2. 01/01/2003  31/01/2004  1   0   7
3. 01/01/2006              1   0   4



Хочется получить следующее

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
Periods to get 
/* 
01/01/2001 31/03/2001 - record 1 from aaa
01/01/2002 31/07/2002 - record 1 from bbb 
01/01/2003 31/05/2003 - date_from record 2 from bbb, date_to is calculated based on merging periods from table aaa and bbb. Since date_to for record 2 from bbb is 31/01/2004, but there are another records from aaa/bbb that are in that period, we need to split the records, that why date_to is 31/05/2003, that's day before 01/06/2003 - record 2 table aaa
01/06/2003 31/01/2004 - same as above logic, 01/06/2003 record 2 table aaa till 31/01/2004
01/02/2004 31/12/2004 - day after previous record (31/01/2004) 01/02/2004 till the last period 31/12/2004 - record 2 table aaa
01/01/2006 31/12/2007 - record 3 bbb till day before 01/01/2008(record 3 table aaa) 31/12/2007
01/01/2008            - last one, record 3 table aaa
*/

Same with business data :
/*
01/01/2001 31/03/2001  1   0   0           
01/01/2002 31/07/2002  1   0   0           
01/01/2003 31/05/2003  1   0   7           
01/06/2003 31/01/2004  7   0   3   1   0   7
01/02/2004 31/12/2004  7   0   3           
01/01/2006 31/12/2007  1   0   4           
01/01/2008             1   8   0   1   0   4
*/




I have the following query that give me above result, but is big and hard to read. And for complex input tables it can be more complex.
Please help to find best algorithm for above requirements. I also look at some PLSQL code (procedure) having as parameter a cursor (for table aaa and bbb) and returning merging periods based on input.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
WITH w0
AS (
 SELECT date_from date_, 'df' cat FROM aaa
  UNION
 SELECT date_from, 'df' FROM bbb
  UNION
 SELECT date_to date_, 'dt' cat FROM aaa
  UNION
 SELECT date_to, 'dt' FROM bbb
)
, w1 AS (
SELECT w0.*
     , LEAD(date_) OVER (ORDER BY date_) lead_dt
     , LEAD(cat) OVER (ORDER BY date_) lead_cat
  FROM w0
)
, w2 AS (
SELECT *
  FROM (
         SELECT date_ + CASE WHEN cat = 'dt' THEN 1 ELSE 0 END df
              , lead_dt - CASE WHEN lead_cat = 'df' THEN 1 ELSE 0 END dt
           FROM w1
       )
 WHERE 1=1
   AND df <= NVL(dt,df) 
)
SELECT w2.df
     , w2.dt
     , aaa.c1
     , aaa.c2
     , aaa.c3
     , bbb.c4
     , bbb.c5
     , bbb.c6
  FROM w2
  LEFT OUTER JOIN aaa
    ON 1=1
   AND ((w2.df BETWEEN aaa.date_from AND NVL(aaa.date_to,w2.df))
         OR
       (aaa.date_from BETWEEN w2.df AND NVL(w2.dt,aaa.date_from))
       )
  LEFT OUTER JOIN bbb
    ON 1=1
   AND ((w2.df BETWEEN bbb.date_from AND NVL(bbb.date_to,w2.df))
         or
       (bbb.date_from BETWEEN w2.df AND NVL(w2.dt,bbb.date_from))
       )
 WHERE c1 IS NOT NULL
    OR c2 IS NOT NULL
    OR c3 IS NOT NULL
    OR c4 IS NOT NULL
    OR c5 IS NOT NULL
    OR c6 IS NOT NULL
; 
...
Рейтинг: 0 / 0
задачка с запросом
    #39586970
Хостес
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Мы говорим на вашем языке
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / задачка с запросом
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]