根据另一个表中的日期,在一个表中的日期范围内获取最新记录

时间:2012-06-20 14:30:59

标签: sql join oracle10g left-join

我在Oracle 10数据库中有以下表格。

TABLE_A列出了ID和相关日期:

ID         DATE
-----------------------
A1234    | 31-Dec-2008 
B5678    | 31-Dec-2009
A1234    | 31-Dec-2010 

TABLE_B,它给出了月末ID的评分:

ID         RATING_DATE   RATING
--------------------------------
A1234    | 31-Dec-2008 | 3
A1234    | 31-Jan-2009 | 3
A1234    | 28-Feb-2009 | 3
A1234    | 31-Mar-2009 | 2
A1234    | 30-Apr-2009 | 2
A1234    | 31-May-2009 | 3
A1234    | 31-Jun-2009 | 2
A1234    | 31-Jan-2010 | 3
A1234    | 28-Feb-2010 | 3
B5678    | 31-Dec-2009 | 4
B5678    | 31-Dec-2010 | 4
B5678    | 31-Jan-2011 | 4
B5678    | 28-Feb-2011 | 4

我需要什么:

对于TABLE_A中的所有IDDATE对,我想在TABLE_B中找到范围内的最新RATING_DATERATING [日期,日期+ 12个月] )。

例如:对于A1234 | 31-Dec-2008,我有兴趣在2008年12月31日至2009年11月30日期间找到最新的RATING_DATERATING。在这里,我希望A1234 | 31-Jun-2009 | 2

我有以下SQL来获取最新的RATING_DATE,但我也无法弄清楚如何获取RATING

SELECT      A.DATE, 
            A.ID, 
            MAX(TABLE_B.RATING_DATE)

FROM        TABLE_A A LEFT JOIN TABLE_B B
            ON
            A.ID = B.ID
            AND
            B.RATING_DATE >= A.DATE
            AND
            B.RATING_DATE < ADD_MONTHS(A.DATE, 12)

GROUP BY    A.DATE, 
            A.ID

有没有办法在没有嵌套连接或其他子查询的情况下完成此操作?

3 个答案:

答案 0 :(得分:1)

这是符合指定要求的查询:

SELECT DISTINCT a.id
     , a.date_
     , LAST_VALUE(b.rating_date) OVER (PARTITION BY a.id, a.date_ ORDER BY b.rating_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_rating_date
     , LAST_VALUE(b.rating)      OVER (PARTITION BY a.id, a.date_ ORDER BY b.rating_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_rating 
  FROM table_a a
  LEFT JOIN table_b b ON b.id = a.id 
       AND b.rating_date >= a.date_ AND b.rating_date < ADD_MONTHS(a.date_,12)
 ORDER BY a.id, a.date_

这是另一种选择:

SELECT DISTINCT a.id
     , a.date_
     , MAX(b.rating_date) KEEP (DENSE_RANK LAST ORDER BY b.rating_date) OVER(PARTITION BY a.id, a.date_) as last_rating_date 
     , MAX(b.rating     ) KEEP (DENSE_RANK LAST ORDER BY b.rating_date) OVER(PARTITION BY a.id, a.date_) as last_rating
  FROM table_a a
  LEFT 
  JOIN table_b b ON b.id = a.id AND b.rating_date >= a.date_ AND b.rating_date < ADD_MONTHS(a.date_,12)
 ORDER BY a.id, a.date_

都返回相同的结果集:

ID    DATE_      LAST_RATING_DATE LAST_RATING
----- ---------- ---------------- -----------
A1234 2008-12-31 2009-06-30                 2
A1234 2010-12-31                             
B5678 2009-12-31 2009-12-31                 4

注意:要设置测试环境,我将datetable_a列的名称更改为date_

create table table_a (id varchar2(5), date_ date);
create table table_b (id varchar2(5), rating_date date, rating int);
alter session set nls_date_format = 'YYYY-MM-DD';
insert into table_a values ('A1234','2008-12-31');
insert into table_a values ('B5678','2009-12-31');
insert into table_a values ('A1234','2010-12-31');
insert into table_b values ('A1234','2008-12-31',3);
insert into table_b values ('A1234','2009-01-31',3);
insert into table_b values ('A1234','2009-02-28',3);
insert into table_b values ('A1234','2009-03-31',2);
insert into table_b values ('A1234','2009-04-30',2);
insert into table_b values ('A1234','2009-05-31',3);
insert into table_b values ('A1234','2009-06-30',2);
insert into table_b values ('A1234','2010-01-31',3);
insert into table_b values ('A1234','2010-02-28',3);
insert into table_b values ('B5678','2009-12-31',4);
insert into table_b values ('B5678','2010-12-31',4);
insert into table_b values ('B5678','2011-01-31',4);
insert into table_b values ('B5678','2011-02-28',4);

答案 1 :(得分:0)

虽然SQL的特定实现可能会使这更容易,但我认为这应该适合你

SELECT v1.id, v1.myDate, v1.rating_date, b2.rating
FROM (SELECT a.id, a.myDate, MAX(b.rating_date) rating_date
      FROM tab_a a 
      LEFT JOIN tab_b b
      ON a.id = b.id
      AND b.rating_date >= a.myDate
      AND b.rating_date < ADD_MONTHS(a.myDate, 12)
      GROUP BY a.id, a.myDate) v1
LEFT JOIN tab_b b2
ON v1.id = b2.id
AND v1.rating_date = b2.rating_date

答案 2 :(得分:0)

MAX(B.RATING) KEEP (DENSE_RANK LAST ORDER BY RATING_DATE)

如果上个月有多个评级,则假定您需要最高评级。

HereFIRSTLAST语法的文档。 (顺便说一下,6月31日不存在。)