2013-04-30 57 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