Oracle连接第一个表中的日期范围和第二个表中的日期的表

时间:2014-11-08 14:40:52

标签: sql database oracle jointable

我在Oracle数据库中有两个表:

第一个表有一个日期范围,我需要帮助编写一个SQL查询来查找第二个表中的所有记录,如下面的结果表所示。日期的前四位数字是年份,最后两位是会话(10-Fall; 20-Spring; 30-Summer)。

1)表1

seqnum |   min_date|   max_date |c_id  

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

2)表2

seqnum |   b_date

1      | 201210
1      | 201220 
1      | 201230
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      | 201230 | 150
1      | 201310 | 150
1      | 201320 | 150
1      | 201330 | 150
1      | 201410 | 200
1      | 201420 | 200
1      | 201430 | 200

如果Table1只有第一条记录,则Table2中的所有日期都必须与c_id 100相关联。

3 个答案:

答案 0 :(得分:0)

小提琴: 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

当table2上的B_DATE低于table1的第一个MIN_DATE时,它将显示最低MIN_DATE的table1中的C_ID(在你的情况下是100,现在)。

当table2上的B_DATE高于table1的最后一个MAX_DATE时,它将显示最高MAX_DATE的table1中的C_ID(在你的情况下是200,现在)。

答案 1 :(得分: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, 201230 from 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 with Table1

  2. 为每个{{1}计算前一个(行按b_date排序})c_id的值为LAGLAST_VALUE +窗口的seqnum }。

  3. 如果c_id为NULL,则显示第一个not null previous值。

答案 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

分享并享受。