Reputation: 323
I have a table like this
| id | name |
----------------------
| A | test a1 |
| A | test a2 |
| A | test a3 |
| B | test b1 |
| B | test b2 |
| A | test a4 |
| C | test c1 |
Id A
has the most values, then B
, etc. How can I return rows ordered by number of names that is associated with id
. I tried this but since I group by id
I lose all names
that are associated with the id
.
SELECT id, name, COUNT(name) as name_count
FROM users
GROUP BY id
ORDER BY name_count DESC
Upvotes: 0
Views: 77
Reputation: 10711
It can be solved even without subquery if there is one column that is unique in users
table. For example, if name
is unique then it will be as follows:
SELECT u1.id, u1.name, COUNT(*) as name_count
FROM users u1
JOIN users u2 ON u1.id = u2.id
GROUP BY u1.name
ORDER BY name_count DESC
Upvotes: 0
Reputation: 1594
You're close. To get around losing the names, you need to join a subquery to handle the counting:
SELECT u.id, u.name
FROM users u
JOIN (
SELECT id, count(1) cnt
FROM users
GROUP BY id) ss
ON u.id = ss.id
ORDER BY ss.cnt DESC
The subquery results in this
+----+-----+
| id | cnt |
+----+-----+
| A | 4 |
| B | 2 |
| C | 1 |
+----+-----+
Joined to your original table we have these rows:
+------+---------+-------+--------+
| u.id | u.name | ss.id | ss.cnt |
+------+---------+-------+--------+
| A | test a1 | A | 4 |
| A | test a2 | A | 4 |
| A | test a3 | A | 4 |
| B | test b1 | B | 2 |
| B | test b2 | B | 2 |
| A | test a4 | A | 4 |
| C | test c1 | C | 1 |
+------+---------+-------+--------+
So we only want to return the columns from the u
users table and sort by the subquery's ss.cnt
. You can select u.*
though it's generally better practice to be explicit in the columns you want your query to return.
You can also add sorting based on u.name
if you want to sort your results within the ID groups:
ORDER BY ss.cnt DESC, u.name
Upvotes: 3