I’m working on a project, and using Knex for it, (though if you give me raw SQL I’m pretty sure I can convert that as well.)
So, here’s the sitch.
I have tables ‘group’ and ‘user_group’.
table 'group' id: integer name: string is_public: boolean table 'user_group' group_id: ref(group.id) user_id: ref(user.id) // don't need user table info for this role: string
What I’d like to do is get a list of all groups
- where is_public is TRUE
- returning the group.name and group.id
- and a count of how many members the group has.
- sorted from most members to least
So an output would look like this:
[
{name: "Clowns", memberCount: 20, id: 3},
{name: "Puppets", memberCount: 12, id: 36},
{name: "Jugglers", memberCount: 5, id: 12},
...
]
Here’s what I’ve got so far:
SELECT COUNT('*') AS memberCount, group.name AS name, group.id AS id
FROM group
INNER_JOIN user_group on group.id = user_group.group_id
WHERE group.is_public = true
AND WHERE user_group.role = "MEMBER"
ORDER BY memberCount ASC`
Am I on the right track?
Advertisement
Answer
I would approach this as:
SELECT g.name, g.id, COUNT(ug.role) AS memberCount
FROM group g LEFT JOIN
user_group ug
ON ug.group_id = g.id AND
ug.role = 'MEMBER'
WHERE g.is_public
GROUP BY g.name, g.id
ORDER BY memberCount DESC;
How is this structured? First, this is using a LEFT JOIN because you want all groups, presumably even those with no members. Because of the LEFT JOIN, the condition on the role is in the ON clause rather than the WHERE clause.
Some other notes:
- Use single quotes for string and date constants. This is the SQL standards.
- Aggregate by all the keys in the
SELECT. - To get results from highest to lowest, use a
DESCORDER BY. - There is no need to specify
= truefor a boolean, although there is no issue either.