2016-10-12 2 views
1

Я знаю, что вопрос, вероятно, плохо объяснен, но я не знаю, как еще объяснить это. У меня есть следующие данные: (упорядочено по дате)Oracle sql: Найти минимальные максимальные последовательные даты в пределах одной группы

DATE GROUP 
    11-Oct-16 A 
    12-Oct-16 A 
    13-Oct-16 A 
    14-Oct-16 B 
    15-Oct-16 B 
    16-Oct-16 A 
    17-Oct-16 A 
    18-Oct-16 C 
    19-Oct-16 C 
    20-Oct-16 C 
    21-Oct-16 C 
    22-Oct-16 A 
    23-Oct-16 A 
    24-Oct-16 A 

Я хочу найти последовательное использование для групп. Результаты, которые я хочу будет объяснить это лучше, чем мне:

GROUP MIN(DATE) MAX(DATE) 
    A 11-Oct-16 13-Oct-16 
    B 14-Oct-16 15-Oct-16 
    A 16-Oct-16 17-Oct-16 
    C 18-Oct-16 21-Oct-16 
    A 22-Oct-16 24-Oct-16 

Любая идея, как сделать это в Oracle SQL? Спасибо.

+0

У вас есть столбец идентификатора, который диктует заказ? – JohnHC

ответ

2

Это может быть способом:

with test("DATE","GROUP") as 
(
    select to_date('11-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('12-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('13-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('14-10-16', 'dd-mm-rr'),'B' from dual union all 
    select to_date('15-10-16', 'dd-mm-rr'),'B' from dual union all 
    select to_date('16-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('17-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('18-10-16', 'dd-mm-rr'),'C' from dual union all 
    select to_date('19-10-16', 'dd-mm-rr'),'C' from dual union all 
    select to_date('20-10-16', 'dd-mm-rr'),'C' from dual union all 
    select to_date('21-10-16', 'dd-mm-rr'),'C' from dual union all 
    select to_date('22-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('23-10-16', 'dd-mm-rr'),'A' from dual union all 
    select to_date('24-10-16', 'dd-mm-rr'),'A' from dual 
) 
select min("DATE"), max("DATE"), "GROUP" 
from (
     select "DATE", 
       "DATE" - row_number() over (partition by "GROUP" order by "DATE") as minDate, 
       "GROUP" 
     from test 
) 
group by "GROUP", minDate 
order by "GROUP", minDate 

Внутренний запрос создает минимальную дату для группы последовательных дат, в то время как внешние один просто агрегаты этой минимальной датой, таким образом, построение строки для каждой группы последовательные даты.

Как в стороне, лучше избегать использования зарезервированных слов в качестве имен столбцов.

+2

Решение работает в этом случае, поскольку даты являются последовательными. Более общее решение будет использовать 'row_number() over (order by date) - row_number() over (раздел по порядку по дате)'. Полезно знать для других, подобных проблем, когда даты могут быть не последовательными. – mathguy

0

Так что я думаю, что правильный ответ был в комментарии @mathguy. Здесь я просто расширяюсь и даю полный полный запрос.

select GROUP_NAME, grp_id, min(date_field) as starting_date, max(date_field) as ending_date 
from (
select DATE_FIELD, GROUP_NAME, 
row_number() over (order by date_field) - row_number() over (partition by group_name order by date_field) as grp_id 
from darber.my_table) innested 
group by GROUP_NAME, grp_id 
order by min(date_field); 

Обратите внимание: я изменил название поля, потому что они давали конфликты в моей базе данных. В этом решении DATE теперь DATE_FIELD, а GROUP теперь GROUP_NAME.

Я нашел это действительно умным и элегантным решением. Я надеюсь, что это поможет другим.

Смежные вопросы