2017-08-25 50 views
3

我有一個Oracle數據庫表結構,其行數通過採訪過程填充,每個「客戶」都可以多次訪問採訪過程,即使是同一天。該表結構如下:SQL查詢顯示數據表中最近一行的數據,或者爲空

Table: Customers 
------------- 
CustomerId 
... 

Table: Questions 
------------- 
QuestionId | QuestionText 
0   | Last Location? 
1   | Last Color? 
2   | Last Food? 
3   | Last Drink? 

Table: Answers 
------------- 
Id | CustomerId | QuestionId | AnswerText | Created_On 
1 0   0   Chicago  08/15/2017 7:56:34 AM 
2 0   0   Laramie  08/16/2017 9:27:23 AM 
3 0   0   Null   08/17/2017 6:34:56 AM 
4 0   1   Null   08/15/2017 7:56:34 AM 
5 0   1   Green  08/16/2017 9:27:23 AM 
6 0   1   Blue   08/17/2017 6:34:56 AM 
7 0   2   Pizza  08/15/2017 7:56:34 AM 
8 0   2   Null   08/16/2017 9:27:23 AM 
9 0   2   Null   08/17/2017 6:34:56 AM 
10 0   3   Null   08/15/2017 7:56:34 AM 
11 0   3   Null   08/16/2017 9:27:23 AM 
12 0   3   Null   08/17/2017 6:34:56 AM 

目前我們顯示「最後一次採訪」通過查詢數據爲最近的時間戳對每一個問題,並顯示結果,它是否有一個值或爲空,這樣:

LastAnswer_QueryResult 
------------- 
Id | CustomerId | QuestionId | AnswerText | Created_On 
3 0   0   Null   08/17/2017 6:34:56 AM 
6 0   1   Blue   08/17/2017 6:34:56 AM 
9 0   2   Null   08/17/2017 6:34:56 AM 
12 0   3   Null   08/17/2017 6:34:56 AM 

的新要求,是展示最新的答案:對於使用值的每個問題,或者爲空,如果這個問題從來沒有得到回答。如果我能得到查詢後的結果爲樣本數據上面看起來像:

MostRecentAnswer_QueryResult 
Id | CustomerId | QuestionId | AnswerText | Created_On 
2 0   0   Laramie  08/16/2017 9:27:23 AM 
6 0   1   Blue   08/17/2017 6:34:56 AM 
7 0   2   Pizza  08/15/2017 7:56:34 AM 
12 0   3   Null   08/17/2017 6:34:56 AM 

到目前爲止,我能想出的最好的辦法是最古老的行插入到一個臨時表,然後在環如果它們存在較新的時間戳,則更新這些值。然後完成後,使用最新的時間戳更新任何空值。有沒有一種方法,我可以做到這一點沒有循環和插入臨時表?

回答

2

救援分析功能!分區爲customeridquestionid,並將row_number()分配給每個分區中的行。如果我們不必擔心answertext is null,我們只需訂購created_on desc

要處理null,我們首先要判斷answertext是否爲null,而不是null。這可以通過case表達式輕鬆完成(參見下文)。

然後在外部查詢中,我們選擇row_number爲1的行(在customeridquestionid的每個組合內)。

select id, customerid, questionid, answertext, ts 
from (
     select id, customerid, questionid, answertext, ts, 
       row_number() over (partition by customerid, questionid 
             order by case when answertext is not null 
                 then 0 end, 
               created_on desc 
           ) as rn 
     from answers 
     ) 
where rn = 1 
; 
+0

感謝拳頭名AnswerText約「時間戳」的字條 - 我不得不混淆實際列名稱,並忘記它是一個保留字。在示例中已修復。 –

0

你可以試試:

select MAX(a.id) ID, a.CustomerId , q.QuestionId,LISTAGG(AnswerText,' * ') WITHIN GROUP (ORDER BY ID) AnswerText, max(a.Created_On) Created_On 
    from Questions q 
    left join Answers a 
    on a.QuestionId = q.QuestionId 
    where a.AnswerText is not null 
    group by a.CustomerId , q.QuestionId 
    UNION ALL 
    select MAX(a.id) ID, a.CustomerId , q.QuestionId ,LISTAGG(AnswerText,' *') WITHIN GROUP (ORDER BY ID) AnswerText, max(a.Created_On) Created_On 
    from Questions q 
    left join Answers a 
    on a.QuestionId = q.QuestionId 
    where a.AnswerText is null AND 
    Q.QuestionId NOT IN(
     select q.QuestionId 
     from Questions q 
     left join Answers a 
     on a.QuestionId = q.QuestionId 
     where a.AnswerText is not null 
     group by a.CustomerId , q.QuestionId 
    ) 
    group by a.CustomerId , q.QuestionId 
    ORDER BY QuestionId 

之後,你會得到之間的「*」

相關問題