views:

96

answers:

2

I'm having real difficulty with a query involving 3 tables. I need to get the 3 newest users per department grouped by department names. The groups should be sorted by the users.dateadded so the department with the newest activity is first. The users can exist in multiple departments so Im using a lookup table that just contains the userID and deptID. My tables are as follows.

Department - depID|name

Users - userID|name|dateadded

DepUsers - depID|userID

The output I need would be

Receiving
John Doe - 4/23/2010
Bill Smith - 4/22/2010

Accounting
Steve Jones - 4/22/2010
John Doe - 4/21/2010

Auditing
Steve Jones - 4/21/2010
Bill Smith - 4/21/2010

+1  A: 

This should give you the 3 last added users for each department (making use of the new ROW_NUMBER function in SQL 2005):

select * from (select  D.name, U.name, U.dateadded, ROW_NUMBER() over (PARTITION BY D.depID ORDER BY U.dateadded DESC) as ROWID from Department as D
join DepUsers as DU on DU.depID = D.depID
join Users as U on U.userID = DU.userID) as T
where T.ROWID <= 3

I didn't exactly understood how you wanted the output to look, but I guess this result set gives you a kick start to get where you're headed.

ntziolis
I get an error saying ROWID doesnt exist. Should that be in a subquery?
Suzy Fresh
Beat me to it! Looks like we were both on a similar track.
BradBrening
@Suzy - Try rapping the entire ting with a select * from (QUERY) and move the where clause out of the subquery, that should work (btw. I updated my post since I had an error in the where clause)
ntziolis
@Suzy - I just included the subquery suggestion into my post
ntziolis
Hey Guys. They both work. I owe you both a beer. THANK YOU!!!!I havent worked with SQL2005 so i totally overlooked row_number. Very cool. I dont have enough data yet to decide but do you know if its better to use the CTE method?
Suzy Fresh
In this instance, a CTE and a subselect are half a dozen of one 6 of the other. I don't think there's a meaningful difference. I like using a CTE however, since I can reuse the query if necessary.
BradBrening
Personally, I think the CTE reads better. Its much easier to understand at a glance
Suzy Fresh
+1  A: 

Try this:

WITH CTE AS
(
SELECT 
  ROW_NUMBER() OVER (PARTITION BY DepartmentName ORDER BY DateAdded DESC) AS RowNumber
  ,D.name AS DepartmentName
  ,U.name AS UserName
  ,U.dateadded AS DateAdded
FROM 
  DepUsers DU
INNER JOIN Users U
  ON DU.userID = U.userID
INNER JOIN Department D
  ON DU.depID = D.depID
)
SELECT
  DepartmentName
  ,UserName
  ,DateAdded
FROM CTE
WHERE RowNumber <= 3
ORDER BY DepartmentName, DateAdded DESC
BradBrening
I had a bad alias on Users in the CTE. Corrected
BradBrening