views:

36

answers:

2

I've been running into the following case repeatedly lately, either I need to apply MAX() or SUM() to one column on a table, but I need DISTINCT sets of values for other columns.

For example consider the following table and associated columns representing details of a login to StackOverflow.

SoUserLogins (OpenIdToken, Name, IpAdress, LoginTimeStamp, QuestionsAsked)

I might want a result set containing users and their last login.

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

But I need distinct values from the other columns. I'm going to wrap this in a common table expression (CTE) because I'm going to use it later and don't want to have to clean up another temporary table.

;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

You could change the MAX(LoginTimeStamp) to SUM(QuestionsAsked) in the code above with a few extra tweaks to see a similar example.

My question, is there a cleaner or more elegant way to deal with these situations?

I am using SQL Server.

+6  A: 

Do you mean this?

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

So you will have multiple rows per OpenIdToken and the same LastLogin value will be repeated for all rows within a group?

Martin Smith
I think this is probably the way I want to go. I thought it wouldn't work with Partition By on multiple columns i.e. (Partition by OpenIdToken, IpAddress), but I was happily mistaken.
Thomas Langston
A: 

If you are under Oracle Database you should consider using Custom *Oracle Analytical Function* which let you agreggate your data by row depending on a column.

As I was writing this, Martin did answer.

But some documentation could be found here (in french)

zor
I think Thomas is using a version of SQLServer, based on the insert into the temporary table. I understand that the more recent versions of SQLServer do have similar analytical functions.
Mark Bannister
I am using SQL Server. I'll update the question to reflect this.
Thomas Langston
@Mark - Yep. If the OP is on a version of SQL Server that supports CTEs (2005+) they will also be on a version that supports these functions.
Martin Smith