2009-10-16 30 views
1

比方說,我有一個表格,其中包含「user_id,日期和分數」,每個用戶每個月只有一個分數,但並不總是在同一天。如何從oracle sql中獲取下個月的條目?

我想要一個具有「user_id,date,score_delta」的查詢,其中score_delta是分數在「date」和下一個月之間會發生多少變化?難道我將不得不做一些跛像TO_DATE(TO_CHAR(日期,...

+0

+1捅了捅我調查分析函數... – DCookie 2009-10-16 22:23:44

回答

1

這裏有一種方法(跛行商算出作爲練習留給讀者):

CREATE TABLE scores (user_id VARCHAR2(32), test_date DATE, score NUMBER); 

INSERT INTO scores VALUES('U1',SYSDATE-61, 85); 
INSERT INTO scores VALUES('U1',SYSDATE-31, 89); 
INSERT INTO scores VALUES('U1',SYSDATE, 92); 
INSERT INTO scores VALUES('U2',SYSDATE-61, 65); 
INSERT INTO scores VALUES('U2',SYSDATE-31, 89); 
INSERT INTO scores VALUES('U2',SYSDATE, 84); 

COMMIT; 

SELECT s1.user_id, s1.test_date, s2.score-s1.score delta 
    FROM scores s1 
     JOIN (SELECT user_id, trunc(test_date,'MM') test_date, score FROM scores) s2 
     ON (s1.user_id = s2.user_id AND 
      trunc(add_months(s1.test_date,1),'MM') = s2.test_date); 

USER_ID       TEST_DATE  DELTA 
-------------------------------- --------- ---------- 
U1        9/15/2009   3 
U1        8/16/2009   4 
U2        9/18/2009   -5 
U2        8/19/2009   24 

編輯 :這是一個緩慢的下午,所以我使用LAG函數決定看看這個解析函數的東西,10g提供(自己再拖動到本世紀;-),並改寫了上面:

SELECT user_id, test_date, score 
    , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) - score delta 
    , LAG(score, 1, NULL) OVER (PARTITION BY user_id ORDER BY test_date DESC) AS next_score 
    FROM scores 
ORDER BY 1, 2 DESC; 

主要生產:

USER_ID       TEST_DATE  SCORE  DELTA NEXT_SCORE 
-------------------------------- ----------- ---------- ---------- ---------- 
U1        10/19/2009   92    
U1        9/18/2009   89   3   92 
U1        8/19/2009   85   4   89 
U2        10/19/2009   84    
U2        9/18/2009   89   -5   84 
U2        8/19/2009   65   24   89 

看,馬!沒有自我加入!現在這是光滑的;-)(順便說一下,解釋計劃表明自聯接效率不高)。

作爲一個跳板,我從asktom.com question開始。

+0

我覺得這是一個相當漂亮的 – 2009-10-16 18:37:53

+0

一個警告:如果表中有很多數據,適當的索引可能會變得必要。 – DCookie 2009-10-16 20:09:10

+1

你錯過了一個測試用例 - 如果你放入多個用戶,你會發現你的查詢會交錯用戶的測試結果,因爲唯一的排序是在test_date上。您應該在ORDER BY test_date之前放置一個PARTITION BY user_id。 – 2009-10-17 06:05:52

0

像這樣的東西應該會返回下個月輸入的user_id,日期和分數。

select user_id, date, score from table where 
date between ((select sysdate from dual) 
and (select add_months(sysdate, 1) FROM dual)); 
+0

OP想要一個當前和下個月的分數之間的三角洲... – DCookie 2009-10-16 19:58:00

相關問題