2012-06-05 57 views
2

我有一個系統,用戶可以完成兩種類型的測試。我需要獲取按其最新測試完成日期排序的DISTINCT個用戶列表。用於從兩個表中選擇ID列和最新日期的SQL語法

爲此,該表也可以被列明爲:

Test_Users 
- Test_User_Id (int) 

Test_1_Results 
- Test_1_Result_Id (int) 
- Test_User_Id (int) 
- Date_Of_Completion (datetime) 

Test_2_Results 
- Test_2_Result_Id (int) 
- Test_User_Id (int) 
- Date_Of_Completion (datetime) 

我可以使用UNION如下高高興興地得到所有不同Test_User_Id的列表:

SELECT Test_User_Id FROM Test_1_Results 
UNION 
SELECT Test_User_Id FROM Test_2_Results 

我可以很容易地使用ORDER BY Date_Of_Completion DESC對這些表格之一的結果進行排序,但我不知道如何使用UNION來做到這一點,或者如果這是繼續進行的最佳方式。

最終我想能夠給別人包內此查詢,如:

SELECT * 
FROM Test_Users 
WHERE Test_User_Id IN (
    //The query i am asking about 
) 
WHERE some_criteria 

但到目前爲止,我還沒有得到任何運氣,而使用UNION這樣做的,我不知道我是什麼做錯了。

我試圖做到這一點的原因是,管理員用戶需要能夠查看已完成測試的每個人的列表,並使用頂部的最近完成項。

我對SQL非常熟悉,但是我從來沒有真的必須在之前使用UNION運算符。

回答

3

這應該工作

SELECT Test_User_Id, max(Date_Of_Completion) AS doc 
FROM ( 
    SELECT Test_User_Id, Date_Of_Completion FROM Test_1_Results 
     UNION ALL 
    SELECT Test_User_Id , Date_Of_Completion FROM Test_2_Results 
) AS temptab 
GROUP BY Test_User_Id 
ORDER BY doc DESC 
+0

+1,但我會將UNION更改爲UNION ALL,因爲我認爲它會表現更好。 – dbenham

+0

@dbenham -tx ...在給定條件下非常有意義....更新了查詢 –

+0

謝謝,很快就會嘗試,看起來很有希望。 @dbenham我認爲'UNION ALL'的性能優勢是因爲不必查找和刪除重複項?無論如何,「GROUP BY」正在完成哪項工作,這樣可以節省兩次嗎? – Ben

1
SELECT t.Test_User_Id, max(Date_Of_Completion) 
FROM Test_Users t 
INNER JOIN 
    (SELECT Test_User_Id, Date_Of_Completion FROM Test_1_Results 
    UNION 
    SELECT Test_User_Id, Date_Of_Completion FROM Test_2_Results) aux on aux.Test_User_Id = t.Test_User_Id 
GROUP BY t.Test_User_Id 
2
;WITH x(u,d) AS 
(
    SELECT u = Test_User_Id, d = MAX(Date_Of_Completion) 
    FROM dbo.Test_1_Results GROUP BY Test_User_Id 
    UNION ALL 
    SELECT Test_User_Id, MAX(Date_Of_Completion) 
    FROM dbo.Test_2_Results GROUP BY Test_User_Id 
), 
y AS 
(
    SELECT u, d, rn = ROW_NUMBER() OVER (PARTITION BY u ORDER BY d DESC) 
    FROM x 
) 
SELECT Test_User_Id = u, Date_Of_Completion = d 
FROM y 
WHERE rn = 1; 
+0

+1不使用相關子查詢。 –

1

我喜歡原來的問題的答案ejb_guy。如果問題擴展了,以至於您還想知道每個用戶的最新結果的測試類型和結果ID,那麼我相信以下內容可以工作(未經測試),並且它應該非常高效。

with All_Tests as (
    select Test_User_Id, 
     Date_Of_Completion, 
     'Test1' as Test_Type, 
     Test_1_Result_Id as Result_Id 
    from Test_1_Results 
    union all 
    select Test_User_Id, 
     Date_Of_Completion, 
     'Test2' as Test_Type, 
     Test_2_Result_Id as Result_Id 
    from Test_2_Results 
), 
Ranked_Tests as (
    select rank() over(partition by Test_User_Id 
         order by Date_Of_Completion desc, 
           Test_Type, 
           Result_Id 
        ) as Test_Rank, 
     Test_User_Id, 
     Date_Of_Completion, 
     Test_Type, 
     Result_Id 
    from All_Tests 
) 
select Test_User_Id, 
     Date_Of_Completion, 
     Test_Type, 
     Result_Id 
    from Ranked_Tests 
where Test_Rank=1 
order by Date_Of_Completion desc, Test_User_Id 
+0

哇謝謝,那是我想包括的東西! – Ben

相關問題