Reputation: 606
Ive been looking at several articles on stack but not been exactly specific to what I need
I have a table with application names, teams, service, directorate and username
I want to bring back the application name, team, service, directorate back of the highest used location (team, service, directorate) based on user, ie usercount
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,count(distinct username) Usercount
FROM
[Windows7data].[dbo].[devices_users_apps_detail] a
GROUP BY
[ApplicationName]
,[Team]
,[Service]
,[Directorate]
ORDER BY
[ApplicationName],
count(distinct username) desc;
I have played with by adding to the above nested subqueries, having statements etc but this has not worked
(Using sub-queries in SQL to find max(count()))
Upvotes: 0
Views: 994
Reputation: 69759
You can use the Analytic function RANK to put your team/service/directorate combination in order of number users by Application Name, then just select the top one for each. The key is that ApplicationName
appears in the group by clause but not in the Partition by clause of the Rank function.
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,UserCount
FROM ( SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,COUNT(DISTINCT username) Usercount,
[Rank] = RANK() OVER(PARTITION BY [Team], [Service], [Directorate]
ORDER BY COUNT(DISTINCT UserName) DESC)
FROM [Windows7data].[dbo].[devices_users_apps_detail] a
GROUP BY [ApplicationName], [Team], [Service], [Directorate]
) t
WHERE t.[Rank] = 1
ORDER BY [ApplicationName], UserCount DESC;
I can't actually work out which way round you want this from the question so I will post both:
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,UserCount
FROM ( SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,COUNT(DISTINCT username) Usercount,
[Rank] = RANK() OVER(PARTITION BY [ApplicationName] ORDER BY COUNT(DISTINCT UserName) DESC)
FROM [Windows7data].[dbo].[devices_users_apps_detail] a
GROUP BY [ApplicationName], [Team], [Service], [Directorate]
) t
WHERE t.[Rank] = 1
ORDER BY [ApplicationName], UserCount DESC;
Upvotes: 3
Reputation: 69524
;With HighestValues
AS
(
SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY [Team], [Service], [Directorate]
ORDER BY Usercount DESC)
FROM
(
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,count(distinct username) Usercount
FROM T a
group by [ApplicationName],[Team],[Service],[Directorate]
)Q
)
SELECT APPLICATIONNAME,TEAM,SERVICE,DIRECTORATE,USERCOUNT
FROM HighestValues
WHERE rn = 1
Upvotes: 0
Reputation: 7344
select *
from
(
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,count(username) Usercount
FROM [Windows7data].[dbo].[devices_users_apps_detail] a
group by [ApplicationName],[Team],[Service],[Directorate]
) b
inner join (
select ApplicationName, Max(UserCount) MaxUserCount
from
(
SELECT [ApplicationName]
,[Team]
,[Service]
,[Directorate]
,count(distinct username) Usercount
FROM [Windows7data].[dbo].[devices_users_apps_detail] a
group by [ApplicationName],[Team],[Service],[Directorate]
) x
)Q on b.ApplicationName = Q.ApplicationName and b.UserCount = q.MaxUserCount
Inner query x gets the lists of Apps, etc with their usercounts. Query Q then get the appname and the max usercount associated with it. This is joined to query b (same as x) which selects the row on b with the maxusercount for each app.
Upvotes: 0
Reputation: 467
Looks OK to me . Does this generate an error? If you want to bring back only the max row then you could try adding a TOP 1 after the SELECT.
Upvotes: 0
Reputation: 13157
SELECT TOP(1)
[ApplicationName]
,[Team]
,[Service]
,[Directorate]
,count(distinct username) Usercount
FROM [Windows7data].[dbo].[devices_users_apps_detail] a
group by
[ApplicationName]
,[Team]
,[Service]
,[Directorate]
order by
Usercount desc;
Upvotes: 0