2010-07-09 72 views
1

我正在嘗試使Teradata SQL查詢返回每個用戶的按時間順序訪問日期 n。例如,Teradata結果中的第n項結果

user | visit_date 
--------------------- 
    a  1/1  
    b  1/10 
    c  1/20 
    a  1/3 
    a  1/4 
    b  1/5 
    c  1/15 
    b  1/9 


> magic_query_for_Second_visit; 
user | second 
------------------ 
    a  1/3 
    b  1/9 
    c  1/20 

我想是這樣的下方,但Teradata的尖叫着說,「有序分析功能在WHERE條款允許的。」我拉了一段時間的頭髮,但沒有取得多大進展。任何人看到這個?

select user, 
    row_number() over (partition by user order by visit_date desc) as rnum 

from visitstable 
    where rnum = 2 

如果我排除where那麼我的結果看起來很有希望...我只是不能提取我所需要的!

user | visit_date | rnum 
--------------------------- 
    a  1/1   1 
    a  1/3   2 
    a  1/4   3 
    b  1/5   1 
    b  1/9   2 
    b  1/10   3 
    c  1/15   1 
    c  1/20   2 

在此先感謝您的幫助!

回答

1
SELECT 
    user 

FROM 
    visitstable 

QUALIFY ROW_NUMBER() OVER (
    PARTITION BY 
     user 
    ORDER BY 
     visit_date DESC) = 2 

我從您的評論中看到,您不一定要依靠Teradata特定的QUALIFY。以下是一種便攜式解決方案(許多RDBMS現在支持CTE):

WITH tmp (user, rnum) AS (
    SELECT 
     user, 
     ROW_NUMBER() OVER (
      PARTITION BY 
       user 
      ORDER BY 
       visit_date DESC) AS rnum 
    FROM 
     visitstable) 
SELECT 
    tmp.* 
FROM 
    tmp 
WHERE 
    tmp.rnum = 2 
+0

謝謝,亞當。 TD不喜歡第一種解決方案。 「QUALIFY BY ROW_NUMBER()」中的「BY」必須去。 第二個讓我的大腦發出嘶嘶聲,這在星期五的早晨很棒。謝謝! – Chris 2010-07-09 15:33:42

+0

糟糕,關於'BY'錯字。我現在編輯了,謝謝。第二個示例是一個可用於主查詢的臨時表。一旦我結束語法,我注意到通過簡單地將現有查詢的第一步移動到'WITH'子句中,可以獲得巨大的性能提升。祝你好運。 – bernie 2010-07-09 15:44:23

0

您使用的是什麼版本的SQL?它看起來像MS SQL Server的後繼版本,所以請嘗試使用「公用表表達式」像這樣...

with cte as ( select user, row_number() over (partition by user order by visit_date desc) as rnum from visitstable )

select * from cte where rnum = 2

的語法可能需要一個小的調整,但是這是一般原則。

+0

這是Teradata ...我會看看我是否可以翻譯您的建議。謝謝。 – Chris 2010-07-09 15:08:15

+1

如果你沒有where子句,你的查詢是否工作,並返回預期的行號?如果是這樣,您可以將結果插入臨時表中,然後從中選擇適當的行號。 – 2010-07-09 15:17:20

+0

是的,臨時表可能可移植工作...我只是想盡量減少臨時表的數量,因爲有數以百萬計的記錄。 – Chris 2010-07-09 15:24:57

1

哦,天堂禁止我應該看看文檔。僅供參考,看起來像qualify可讓您指定有序的分析約束。然而,qualify沒有ANSI,所以我仍然端出點便攜式解決方案...

我可以這樣做:

select user, 
    row_number() over (partition by user order by visit_date desc) as rnum 

from visitstable 
qualify rnum=2 

...並獲得...

user | visit_date | rnum 
----------------------------- 
    a  1/3   2 
    b  1/9   2 
    c  1/20   2 

將它書籤! :)

+0

+1找到你自己的解決方案。 – bernie 2010-07-09 15:51:05