我在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中的所有ID
,DATE
对,我想在TABLE_B中找到范围内的最新RATING_DATE
和RATING
[日期,日期+ 12个月] )。
例如:对于A1234 | 31-Dec-2008
,我有兴趣在2008年12月31日至2009年11月30日期间找到最新的RATING_DATE
和RATING
。在这里,我希望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
有没有办法在没有嵌套连接或其他子查询的情况下完成此操作?
答案 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
注意:要设置测试环境,我将date
中table_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)
如果上个月有多个评级,则假定您需要最高评级。
Here是FIRST
和LAST
语法的文档。 (顺便说一下,6月31日不存在。)