0

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

列出 ID 和相关日期的 TABLE_A:

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 中的所有ID,DATE对,我想在 [DATE, DATE + 12 个月) 范围内找到最新的RATING_DATE和TABLE_B 中的对。RATING

例如:对于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

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

4

3 回答 3

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

注意:为了设置测试环境,我将date列的名称更改table_adate_.

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);
于 2012-06-20T20:45:51.673 回答
0
MAX(B.RATING) KEEP (DENSE_RANK LAST ORDER BY RATING_DATE)

这假设如果上个月有多个评级,您想要最大的评级。

是文档FIRSTLAST语法。(顺便说一句,6 月 31 日不存在。)

于 2012-06-20T18:45:57.067 回答
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
于 2012-06-20T14:55:34.013 回答