Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 задачка про диапазоны  [new]
Нексус
Guest
есть одна таблица T1 с произвольными датами
и есть вторая таблица T2, в которой тоже даты
но они образуют некоторые диапазоны из непрерывных дат
или наоборот, можно считать это множеством дат с пропусками

нужно для каждой даты из T1
найти дату в T2
которая является концом диапазона в который попадает дата из T1
либо, если дата из T1 попадает в пропуск, концом ближайшего диапазона в будущем

даты сортируются в порядке возрастания

так вот, в чем задачка
в T1 записей много, да и в T2 немало
поэтому хотелось бы быстроработающее решение

PS: имхо, чтобы определить диапазоны, ORDER BY неизбежен
так вот.... хотелось бы чтобы ORDER BY выполнялся _один_ раз

но вот как это сделать - мне не хватает гибкости мышления

заранее благодарен
8 сен 10, 12:08    [9402928]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
comphead
Member

Откуда: Киев
Сообщений: 3390
Нексус,

приведите пример, плз
8 сен 10, 12:12    [9402982]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Нексус,

из постановки следует, что для строк таблицы 1 нужно извлечь из таблицы 2 строку,
содержащую ближайшую t2.d2 >= t1.d

типичный keep
8 сен 10, 12:16    [9403023]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
Нексус
Guest
orawish
Нексус,

из постановки следует, что для строк таблицы 1 нужно извлечь из таблицы 2 строку,
содержащую ближайшую t2.d2 >= t1.d


нет
это начало диапазона либо вообще середина
а нужен конец

пример

T1:

02.09.10
05.09.10
07.09.10
11.09.10

T2:

01.09.10
04.09.10
05.09.10
06.09.10
11.09.10
12.09.10

нужно:

02.09.10, 06.09.10
05.09.10, 06.09.10
07.09.10, 12.09.10
11.09.10, 12.09.10
8 сен 10, 12:31    [9403178]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Нексус
orawish
Нексус,

из постановки следует, что для строк таблицы 1 нужно извлечь из таблицы 2 строку,
содержащую ближайшую t2.d2 >= t1.d


нет
это начало диапазона либо вообще середина
а нужен конец
..

имхо, таки не нет, а да

ну, разве что не >= , а строго >
8 сен 10, 12:38    [9403275]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
Нексус
Guest
orawish
Нексус
orawish
Нексус,

из постановки следует, что для строк таблицы 1 нужно извлечь из таблицы 2 строку,
содержащую ближайшую t2.d2 >= t1.d


нет
это начало диапазона либо вообще середина
а нужен конец
..

имхо, таки не нет, а да

ну, разве что не >= , а строго >


возьмем пример выше
дата 02.09.10
и диапазон 04....06
ближайшую "строго >" это 04.09.10
а нужно - 06.09.10

или я чего-то не понимаю
8 сен 10, 13:06    [9403608]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
тУпик
Guest
with t1 as (select to_date('02.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('07.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual),
     t2 as (select to_date('01.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('04.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('06.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('12.09.10','dd.mm.yyyy') from dual)
     Select t1.d d1, min(t3.d2)
     from t1, 
      (SELECT max(D) D2 /* здесь уже только концы всех диапазонов из T2 по идее ну и начало первого */
        FROM (select d,
                     sum(strt_gr) over (order by d) grp_num
               from 
                  (select  d, 
                           case when d > 1 + max(d) over (order by d rows between unbounded preceding and 1 preceding) then 1 end strt_gr
                   FROM T2)
              )              
     GROUP BY grp_num) t3
     where t3.d2(+)>=t1.d
     group by t1.d
Ку? :)
8 сен 10, 13:26    [9403864]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
lLocust
Guest
Ку2 )

with t1 as (select to_date('02.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('07.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual),
     t2 as (select to_date('01.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('04.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('06.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('12.09.10','dd.mm.yyyy') from dual)
select  d,
        (   select  min(t3.d)
            from    (select  d,
                        case when d + 1<nvl(lead (d) over (order by d),d+2) then 1 end end_group 
                    FROM    t2) t3
            where   t3.d>=t1.d and end_group=1) d2
from    t1
8 сен 10, 13:50    [9404108]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Нексус
..
или я чего-то не понимаю

до того, как искать конец подходящего диапазона, разумеется,
надо определить концы всех диапазонов.
~
with 
     t1 as (select to_date('02.09.10','dd.mm.yyyy') d from dual
                union all
                select to_date('05.09.10','dd.mm.yyyy') from dual
                union all
                select to_date('07.09.10','dd.mm.yyyy') from dual
                union all
                select to_date('11.09.10','dd.mm.yyyy') from dual),
     t2 as (select to_date('01.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('04.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('06.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('12.09.10','dd.mm.yyyy') from dual)
,t21 as (select d ,lead(d) over(order by d) as d1
           from t2)
,t22 as (select d as d2
           from t21
          where nvl(d1,d+2) > d+1)
         select d
               ,min(d2) keep (dense_rank first order by d2) d2
           from t1,t22
          where d2>d
       group by d;
8 сен 10, 13:50    [9404117]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
тУпик
Guest
lLocust, о красивенько :)
8 сен 10, 13:58    [9404200]     Ответить | Цитировать Сообщить модератору
 Re: задачка про диапазоны  [new]
Нексус
Guest
lLocust
Ку2 )

with t1 as (select to_date('02.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('07.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual),
     t2 as (select to_date('01.09.10','dd.mm.yyyy') d from dual
            union all
            select to_date('04.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('05.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('06.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('11.09.10','dd.mm.yyyy') from dual
            union all
            select to_date('12.09.10','dd.mm.yyyy') from dual)
select  d,
        (   select  min(t3.d)
            from    (select  d,
                        case when d + 1<nvl(lead (d) over (order by d),d+2) then 1 end end_group 
                    FROM    t2) t3
            where   t3.d>=t1.d and end_group=1) d2
from    t1


Спасибо большое.
То что надо.
И план отличный.
8 сен 10, 14:28    [9404464]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить