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’.
x
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
DESC
ORDER BY
. - There is no need to specify
= true
for a boolean, although there is no issue either.