Reputation: 73
I know I'm just making a simple error somewhere, but I can't figure it out. I'm sure this is beyond easy.
I have a table with user ids, names, and a profile. I'm trying to count the number of users with each profile, and group them by the profile. Below is a sample of fake data.
This is the kind of output I'm looking for:
Below are a few simplified versions of what I tried so far:
select UserID, Name, Profile
from test_db
group by profile
Another attempt:
select UserID, Name, Profile, count(Profile)
from test_db
group by profile, UserID, Name
Neither give me what I'm looking for. I just get a long list of rows and for the count they just all have a 1 by them. I know I'm making it harder than it needs to be.
Thanks in advance!
Upvotes: 0
Views: 4561
Reputation: 164054
Use ROW_NUMBER()
and COUNT()
window functions:
SELECT CASE WHEN t.rn = 1 THEN t.Profile END Profile,
CASE WHEN t.rn = 1 THEN t.counter END counter,
t.User_ID,
t.Name
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Profile ORDER BY Name) rn,
COUNT(*) OVER (PARTITION BY Profile) counter
FROM tablename t
) t
ORDER BY t.Profile, t.rn
I used the column Name
to sort the rows in each Profile
, but you can use any other column by making the change inside the OVER
clause of ROW_NUMBER()
.
Upvotes: 1
Reputation: 50019
Chances are whatever RDBMS you are using supports window functions which you'll need for getting counts in an unaggregated result set like this.
SELECT UserID
,Name
,Profile
,Count(*) OVER (PARTITION BY Profile)
FROM test_db
ORDER BY Profile;
That won't give you blanks for repeating Profile
and Count
columns, but that's not really a thing that RDBMS's do so this is probably as close as you get.
You'll notice there is no GROUP BY
here. You don't want to GROUP BY anything since you want the same number of records outputted as you put in. That Count(*) OVER (PARTITION BY Profile)
will group records by distinct Profile
value and then give you a count for each group/partition.
Upvotes: 3