2013-04-30 55 views
1

我有一個表,看起來像這樣:SQL選擇獨特的屬性中最後一次出現

Date | AttributeId | Score | 
4/4/2013   1   0.64  
4/6/2013   2   0.35 
4/6/2013   1   0.86 
4/4/2013   5   0.34 
4/4/2013   4   0.23 
4/7/2013   3   0.54 
4/8/2013   1   0.66 

我可以構建在MS SQL查詢,使我得到的只是一個特定 屬性Id的最後一次出現。如果有幫助

Date | AttributeId | Score |  
4/6/2013   2   0.35 
4/4/2013   5   0.34 
4/4/2013   4   0.23 
4/7/2013   3   0.54 
4/8/2013   1   0.66 

,我知道,只有5 AttributeIDs(1-5),他們不會改變:從上面的例子中,查詢將返回此。

目前我查詢最近15條記錄(並希望那些記錄包含我所有的5個屬性),然後在應用程序級別提取所有5個屬性的最新分數。
有沒有更好的解決方案?

編輯:
另外,如果我有DateUserIdAttributeIdScore,可我不知組我的結果通過UserId
當我嘗試你的答案時,我看到我只獲得最新的結果,不管哪個UserId
我對不起你們,我應該提到UserId越早

編輯2: 我需要通過屬性來獲得最新的分數爲每一位用戶和超過平均的屬性他們的得分。 樣品看起來是這樣的:

Date | UserId | AttributeId | Score | 
4/4/2013  1   1   0.64  
4/6/2013  1   1   0.35 
4/6/2013  2   1   0.86 
4/4/2013  1   3   0.34 
4/4/2013  2   3   0.23 
4/7/2013  2   1   0.54 
4/8/2013  1   5   0.69 
4/4/2013  2   4   0.27 
4/7/2013  2   2   0.54 
4/9/2013  1   4   0.66 
4/9/2013  2   2   0.58 
4/10/2013  1   4   0.66 
4/9/2013  1   2   0.33 
4/11/2013  2   5   0.10 

第一個結果是這樣的:

Date | UserId | AttributeId | Score | 
4/6/2013  1   1   0.64  
4/9/2013  1   2   0.33 
4/4/2013  1   3   0.34 
4/10/2013  1   4   0.66 
4/8/2013  1   5   0.69 
4/7/2013  2   1   0.86 
4/9/2013  2   2   0.58 
4/4/2013  2   3   0.23 
4/4/2013  2   4   0.27 
4/11/2013  2   5   0.10 

而且通過UserId平均得分在最後的結果是:

UserId | AverageScore | 
    1   0.532  
    2   0.408 
+0

有多少不同的屬性相比,記錄你有人數是多少? – Quassnoi 2013-04-30 08:58:34

+0

和多少條記錄? – Quassnoi 2013-04-30 09:01:30

+0

對不起,有5個屬性和大約1000條記錄 – ttkalec 2013-04-30 09:02:30

回答

3
SELECT * 
FROM (
     SELECT *, 
       ROW_NUMBER() OVER (PARTITION BY attributeId ORDER BY [date] DESC) rn 
     FROM mytable 
     ) q 
WHERE rn = 1 

如果你有一個固定的列表,但幾個屬性(或與他們的表),該查詢可能更有效:

SELECT * 
FROM attribute a 
OUTER APPLY 
     (
     SELECT TOP 1 
       [date], score 
     FROM score s 
     WHERE attributeId = a.id 
     ORDER BY 
       [date] DESC 
     ) s 

創建索引:

CREATE INDEX 
     ix_score_attribute_date__score 
ON  score (attributeId, date) 
INCLUDE (score) 

此查詢可以快速運行。

更新:

要選擇每個用戶的最新得分的平均值,用這個:

SELECT userId, AVG(score) 
FROM (
     SELECT userId, score 
     FROM (
       SELECT * 
         ROW_NUMBER() OVER (PARTITION BY userId, attributeId ORDER BY [date] DESC) rn 
       FROM score 
       ) s 
     WHERE rn = 1 
     ) q 
GROUP BY 
     userId 
+0

只是好奇,是否有可能爲此編寫一個可擴展的查詢跨平臺? – Strawberry 2013-04-30 09:10:48

+0

草莓:不是一個有效的,沒有。您可以使用將表連接到「SELECT attributeId,MAX(DATE)」,但這不會處理重複,並且對於少數屬性來說效率不高。 – Quassnoi 2013-04-30 09:13:09

+0

非常感謝你親愛的先生:) – ttkalec 2013-04-30 16:28:46

1
WITH records 
AS 
(
    SELECT [Date], AttributeId, Score, 
      DENSE_RANK() OVER (PARTITION BY AttributeId ORDER BY [Date] DESC) rn 
    FROM TableName 
) 
SELECT [Date], AttributeId, Score 
FROM records 
WHERE rn = 1 
+0

如果你在'[date]'上有聯繫,'DENSE_RANK'會返回你可能想要或不想要的重複。 – Quassnoi 2013-04-30 08:57:26

+0

@Quassnoi這正是查詢的目的。它處理重複。 – 2013-04-30 08:58:08

+2

如果最後的記錄共享'[Date]',那麼您的查詢將返回單個'attributeId'的多個記錄。這也是可能或不可取的,我只是想提一下這個事實。 – Quassnoi 2013-04-30 09:00:17