Вам нужен календарь , который будет возвращать нужные даты - первый понедельник (который следует за сегодня ), а затем первый понедельник каждого месяца.Вот как это делается:
SQL> with
2 this_year as
3 (select trunc(sysdate) + level - 1 datum
4 from dual
5 connect by level <= date '2019-12-31' - trunc(sysdate) + 1
6 ),
7 formatted as
8 (select datum,
9 to_char(datum, 'd') day_num,
10 to_char(datum, 'dy', 'nls_date_language = english') day_name
11 from this_year
12 )
13 select *
14 from formatted f
15 where 1 = 1
16 and f.datum = (select min(f1.datum)
17 from formatted f1
18 where f1.day_num = 1
19 and to_char(f1.datum, 'yyyymm') = to_char(f.datum, 'yyyymm')
20 );
DATUM D DAY_NAME
---------- - ------------
10.06.2019 1 mon
01.07.2019 1 mon
05.08.2019 1 mon
02.09.2019 1 mon
07.10.2019 1 mon
04.11.2019 1 mon
02.12.2019 1 mon
7 rows selected.
SQL>
Что он делает?
this_year
CTE возвращает все даты с «сегодня» по 31 декабря 2019 года. Если есть какая-то МАКСИМАЛЬНАЯ дата, которую вы можете использовать- используйте его formatted
CTE - это промежуточный этап;если вы запустите его, вы увидите, что day_num
представляет порядковый номер дня (1, 2, ... 7), а day_name
возвращает их сокращенные имена (mon, tue, ...).Нас интересует день номер 1, поскольку он представляет понедельники - , итоговый
select
возвращает желаемый результат - первый понедельник каждого месяца
Когда у вас есть эти даты, используйте их вваш текущий запрос.Как?Простой вариант - создать представление на основе такого запроса, например,
SQL> create or replace view v_mondays as
2 with
3 this_year as ...
<snip>
View created.
SQL> select * From v_mondays;
DATUM D DAY_NAME
---------- - ------------
10.06.2019 1 mon
01.07.2019 1 mon
<snip>
7 rows selected.
SQL>
Expanded, ваш запрос может выглядеть следующим образом:
select
d.item,
i.description,
d.market,
case
when d.loc like 'U%' then 'US'
when d.loc like 'M%' then 'MX'
when d.loc like 'C%' then 'CA'
else 'EXP'
end as country,
d.start_date as startdate,
sum(d.demandqty) as qty
from demand d join item i on d.item = i.item
join v_mondays m on m.datum = d.start_date --> join with Mondays
group by d.item, i.description, d.market, d.loc,d.start_date;