2014-11-08 2 views
0

У меня есть две таблицы в базе данных Oracle:Oracle Присоединяйтесь таблицы с диапазоном дат в первой таблице и даты во второй таблице

Первая таблица имеет диапазон дат и мне нужна помощь в написании запроса SQL, чтобы найти все записи из второй таблицы, как в приведенной ниже таблице результатов. Первые четыре цифры в дате - год, а последние два - сеанс (10-осень, 20-весна, 30 лет).

1) Table1

seqnum | min_date| max_date |c_id 

1  | 201210 | 201210 | 100  
1  | 201220 | 201330 | 150  
1  | 201410 | 201410 | 200 

2) Table2

seqnum | b_date 

1  | 201210 
1  | 201220 
1  | 2
1  | 201310 
1  | 201320 
1  | 201330 
1  | 201410 
1  | 201420 
1  | 201430 

3) Таблица результатов

seqnum | b_date | c_id 

1  | 201210 | 100 
1  | 201220 | 150 
1  | 2| 150 
1  | 201310 | 150 
1  | 201320 | 150 
1  | 201330 | 150 
1  | 201410 | 200 
1  | 201420 | 200 
1  | 201430 | 200 

Если Table1 есть только первая запись, то все даты в Table2 должны быть связанный только с c_id 100.

+0

Каково соотношение между таблицами 1 и 2? –

ответ

0

Чтобы сделать это как можно проще:

select t2.seqnum, t2.b_date, coalesce(t1.c_id, t3.max_id) as c_id 
    from table2 t2 
    left outer join table1 t1 
    on t2.b_date between t1.min_date and t1.max_date 
    cross join (select max(c_id) as max_id from table1) t3 
    order by t1.c_id, t2.b_date 

SQLFiddle here

Делите и наслаждайтесь.

0

Fiddle:http://sqlfiddle.com/#!4/45c72/10/0

select t2.seqnum, 
     t2.b_date, 
     case when t2.b_date < min_rg then x.c_id 
      when t2.b_date > max_rg then y.c_id 
       else t1.c_id 
       end as c_id 
    from (select min(min_date) as min_rg, max(max_date) as max_rg from table1) z 
    join table1 x 
    on x.min_date = z.min_rg 
    join table1 y 
    on y.max_date = z.max_rg 
cross join table2 t2 
    left join table1 t1 
    on t2.b_date between t1.min_date and t1.max_date 
order by b_date 

Когда B_DATE на table2 ниже, чем первый MIN_DATE на table1 он покажет C_ID из table1 низшего MIN_DATE (100 в вашем случае, прямо сейчас).

Когда B_DATE в таблице2 выше, чем последний MAX_DATE в таблице1, он отображает C_ID из таблицы 1 наивысшего значения MAX_DATE (200 в вашем случае, прямо сейчас).

0
with table1 as (
select 1 seqnum, 201210 min_date, 201210 max_date, 100 c_id from dual 
union all select 1, 201220, 201330, 150 from dual 
union all select 1, 201410, 201410, 200 from dual 
), 
table2 as (
select 1 seqnum, 201210 b_date from dual 
union all select 1, 201220 from dual 
union all select 1, 2from dual 
union all select 1, 201310 from dual 
union all select 1, 201320 from dual 
union all select 1, 201330 from dual 
union all select 1, 201410 from dual 
union all select 1, 201420 from dual 
union all select 1, 201430 from dual 
),  
semi as (
select t2.seqnum, t2.b_date, t1.c_id, 
     -- since Oracle 11g 
     --lag(c_id IGNORE NULLS) over(partition by t2.seqnum order by t2.b_date) prev_c_id 
     last_value(c_id IGNORE NULLS) over(partition by t2.seqnum 
              order by t2.b_date 
              ROWS BETWEEN UNBOUNDED PRECEDING 
                AND 1 PRECEDING) prev_c_id 
from table2 t2 left join table1 t1 
    on t2.seqnum = t1.seqnum and t2.b_date between t1.min_date and t1.max_date 
) 
select seqnum, b_date, nvl(c_id, prev_c_id) c_id 
from semi; 

Это может быть сделано с аналитическими функциями.

  1. левого присоединиться к Table2 с Table1

  2. Вычислить предыдущее (строки упорядочены по b_date) не нулевому значению c_id с (LAG или LAST_VALUE + оконным) для каждого seqnum.

  3. Если c_id имеет значение NULL, тогда отобразите первое ненулевое предыдущее значение.

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