Главная > SQL > Разбить период на месяца


Разбить период на месяца

with t as (
  select to_date('03-05-2010','dd-mm-yyyy') d1,
         to_date('26-08-2010','dd-mm-yyyy') d2
  from dual
)
--
select decode(level,1,d1,trunc(add_months(d1,level-1),'mm')) as date_from,
       case when add_months(trunc(d1,'mm'),level)>d2 then d2
            else last_day(add_months(d1,level-1))
       end date_to
from t
connect by add_months(trunc(d1,'mm'),level-1) < d2;


DATE_FROM   DATE_TO
----------- -----------
03.05.2010  31.05.2010
01.06.2010  30.06.2010
01.07.2010  31.07.2010
01.08.2010  26.08.2010

Если хотим, чтобы в период входил 1 день последнего месяца, то :

with t as (
  select to_date('03-05-2010','dd-mm-yyyy') d1,
         to_date('01-08-2010','dd-mm-yyyy') d2
  from dual
)
--
select decode(level,1,d1,trunc(add_months(d1,level-1),'mm')) as date_from,
       case when add_months(trunc(d1,'mm'),level)>d2 then d2
            else last_day(add_months(d1,level-1))
       end date_to
from t
connect by add_months(trunc(d1,'mm'),level-1) <= d2;

DATE_FROM   DATE_TO
----------- -----------
03.05.2010  31.05.2010
01.06.2010  30.06.2010
01.07.2010  31.07.2010
01.08.2010  01.08.2010


Похожие записи:

  1. underchronos
    13 Апрель 2011 в 15:06 | #1

    connect by add_months(d1,level-1) < d2;

    немножко некорректно, необходимо именно не d1, а trunc(d1, 'mm'), иначе пропадет последний период при условии что число начала периода выше числа из окончания периода.

  2. rudev
    14 Апрель 2011 в 07:40 | #2

    @underchronos
    А можно пример входных данных для неправильной работы запроса?

  3. underchronos
    14 Апрель 2011 в 15:47 | #3

    Конечно:
    ’27-05-2010′ and ’26-08-2010′

    Результат получится:
    27.05.2010 31.05.2010
    01.06.2010 30.06.2010
    01.07.2010 26.08.2010
    — два последних периода вместе схлопнулись из-за того, что 27.08.2010 > 26.08.2010, а при корректировке 01.08.2010 <= 26.08.2010
    — надо даже еще условие не '<' , а '<=' иначе схлопнется при условии, что дни одинаковые в условиях.
    — кстати, как вариант условия выхода из "рекурсивного вызова" — использование функции months_between (кому как нравится).

  4. underchronos
    14 Апрель 2011 в 15:49 | #4

    Кстати, отличный блог. Опыта у меня в программировании под Оркала никакого, но в администрирования есть. Интересные заметки есть.

  5. rudev
    15 Апрель 2011 в 06:41 | #5

    @underchronos
    Спасибо. Учёл замечание.

  6. Gudvin
    22 Январь 2013 в 15:00 | #6

    Если на вход подать больше одной строки:

    with t as (   
    select to_date('03-05-2010','dd-mm-yyyy') d1,  to_date('26-08-2010','dd-mm-yyyy') d2 from dual 
    union all
    select to_date('03-10-2010','dd-mm-yyyy') d1,  to_date('26-11-2010','dd-mm-yyyy') d2 from dual 
    )  
    

    результаты дублируются. Как побороть?

  7. 2 Февраль 2013 в 13:16 | #7

    Не «на месяца», автор, это не по-русски. Это по-бухгалтерски. Правильно будет — на месяцы.

  8. чародей
    26 Июнь 2019 в 21:22 | #8

    Если на вход подать больше одной строки:

    результаты дублируются. Как побороть?

    не знаю как, но если добавить два волшебных сравнения, то работает

    connect by add_months(trunc(d1,'mm'),level-1) <= d2
    and prior id = id 
    and prior dbms_random.random is not null

    столбец «id» (название неважно) надо добавить в таблицу «t» и обеспечить, чтобы у каждого интервала оно было уникальным.

  1. Пока что нет уведомлений.