#sql #oracle #oracle10g
Вопрос:
Я работаю над запросом, в котором в базе данных могут быть все даты с соответствующими данными, а могут и не быть. Данные в таблице следующие:
ID DATE
1 6/1/2021
1 6/2/2021
1 6/3/2021
1 6/4/2021
1 6/5/2021
1 6/8/2021
2 6/4/2021
2 6/5/2021
2 6/8/2021
Ожидаемый Результат:
ID DATE
1 6/1/2021
1 6/2/2021
1 6/3/2021
1 6/4/2021
1 6/5/2021
1 6/6/2021
1 6/7/2021
1 6/8/2021
2 6/1/2021
2 6/2/2021
2 6/3/2021
2 6/4/2021
2 6/5/2021
2 6/6/2021
2 6/7/2021
2 6/8/2021
Поэтому я попробовал выполнить следующий запрос, LEFT JOIN
который вернет всю требуемую дату:
WITH all_dates AS (SELECT TO_DATE('01-JUN-2021') ROWNUM - 1 AS d FROM dual CONNECT BY ROWNUM <= ADD_MONTHS(TO_DATE('01-JUN-2021'), 12 ) - TO_DATE('01-JUN-2021'))
SELECT T.ID, T.DATE FROM all_dates LEFT JOIN TABLE_HERE t on T.DATE = all_dates.d WHERE all_dates.d <= '08-JUN-2021' AND T.ID ('1', '2') AND T.DATE >= '01-JUN-2021' AND T.DATE <= '08-JUN-2021' ORDER BY all_dates.d;
К сожалению, это возвращает только данные с совпадающими датами, а не отсутствующие (отсутствующие будут объединены с фактическими). Есть ли что-нибудь, что мне нужно сделать, чтобы это сработало?
Ответ №1:
Для меня это выглядит как следующий запрос; читайте комментарии в коде:
SQL> with
2 your (id, datum) as
3 -- your sample data
4 (select 1, date '2021-06-01' from dual union all
5 select 1, date '2021-06-02' from dual union all
6 select 1, date '2021-06-08' from dual union all
7 --
8 select 2, date '2021-06-08' from dual union all
9 select 2, date '2021-06-04' from dual union all
10 select 2, date '2021-06-08' from dual
11 ),
12 calendar as
13 -- you already know how to create a calendar; I'm using only 10 days for simplicity
14 (select date '2021-06-01' level - 1 datum
15 from dual
16 connect by level <= 10
17 ),
18 ids (id) as
19 -- distinct ID values from your sample table (returns two rows; "1" and "2")
20 (select distinct id from your)
21 -- final query: cross join of calendar and distinct ID values
22 select c.datum, i.id
23 from calendar c cross join ids i
24 order by i.id, c.datum;
В результате получается
DATUM ID
-------- ----------
01.06.21 1
02.06.21 1
03.06.21 1
04.06.21 1
05.06.21 1
06.06.21 1
07.06.21 1
08.06.21 1
09.06.21 1
10.06.21 1
01.06.21 2
02.06.21 2
03.06.21 2
04.06.21 2
05.06.21 2
06.06.21 2
07.06.21 2
08.06.21 2
09.06.21 2
10.06.21 2
20 rows selected.
SQL>