2010-09-29 23 views
1

我最近一直在反复地遇到以下情况,要么我需要将MAX()或SUM()应用于表上的一列,但我需要为其他列设置DISTINCT值集。如何将sql聚合函数与独特的更清晰地结合起来?

例如,考虑下表和表示登录到StackOverflow的详细信息的相关列。

SoUserLogins(OpenIdToken,名称,IpAdress,LoginTimeStamp,QuestionsAsked)

我可能要包含用户和他们的最后一次登录的结果集。

SELECT DISTINCT 
    OpenIdToken, 
    MAX(LoginTimeStamp) 
INTO #tmpLastLogin 
FROM SoUserLogins 
GROUP BY OpenIdToken 

但我需要不同的值从其他列。我将把它包装在一个公共表格表达式(CTE)中,因为我稍后会使用它,并且不想清理另一个临时表。

;WITH tmpLastLogin_CTE AS (
SELECT DISTINCT 
    SOL.OpenIdToken, SOL.Name, SOL.IpAdress, SOL.QuestionsAsked 
    TTL.LastLogin 
FROM SoUserLogins SOL 
JOIN #tmpLastLogin TLL ON SOL.OpenIdToken = TLL.OpenIdToken 
) 
--Extra SQL using tmpLastLogin_CTE goes here 

你可以改变MAX(LoginTimeStamp)总结(QuestionsAsked)在上面的代码有一些额外的调整,以看到类似的例子。

我的问题,是否有更清洁或更优雅的方式来处理这些情况?

我正在使用SQL Server。

+0

我建议删除第一个查询DISTINCT关键字,因为它是多余的,令人困惑 - GROUP BY子句确保只有不同OpenIdToken的值将返回。 – 2010-09-30 12:49:52

回答

7

你的意思是?

SELECT DISTINCT 
    SOL.OpenIdToken, SOL.Name, SOL.IpAdress, SOL.QuestionsAsked, 
    MAX(LoginTimeStamp) OVER (PARTITION BY OpenIdToken) AS LastLogin 
FROM SoUserLogins SOL 

所以你必须每OpenIdToken和相同LastLogin值将被重复的一组中的所有行多行?

+0

我想这可能是我想要去的方式。我认为它不适用于多列的分区依据,即(分区由OpenIdToken,IpAddress),但我很高兴错误。 – 2010-09-30 13:33:25

0

如果您正在Oracle数据库你应该考虑使用自定义 * 甲骨文分析功能 * 这让您根据一列列agreggate您的数据。

在我写这篇文章时,马丁做了答案。

但一些文件可以发现here(法语)

+0

我想托马斯正在使用SQLServer的一个版本,基于插入到临时表中。我知道最新版本的SQLServer确实有类似的分析功能。 – 2010-09-30 12:51:54

+1

我正在使用SQL Server。我会更新这个问题来反映这一点。 – 2010-09-30 13:17:16

+1

@Mark - 是的。如果OP位于支持CTE(2005+)的SQL Server版本上,则它们也将支持支持这些功能的版本。 – 2010-09-30 13:22:43