{"id":"code-col-sql-left-join-active-member-counts","audience":"college","category":"coding","track":"coding","technique":"context","title":"Count members per club, including clubs with none","free":false,"task":"For the student activities app, list every chartered club (is_chartered = 1) with its member count, including clubs with zero. Both 'active' and 'pending' count (pending members were approved offline), alumni don't, and that condition must not drop zero-member clubs. Columns exactly club_name and member_count, sorted by member_count highest first, then club_name. Write one SQLite query in exactly 1 code block of at most 10 lines, under 25 words of text.","materialLabel":"The schema and sample rows (attached to your prompt automatically)","material":"-- activities.db (SQLite) - \"ClubHub\" project for CS 3300, team Kestrel\n\nCREATE TABLE clubs (\n  id            INTEGER PRIMARY KEY,\n  name          TEXT NOT NULL UNIQUE,\n  is_chartered  INTEGER NOT NULL      -- 1 = official, 0 = interest group\n);\n\nCREATE TABLE memberships (\n  club_id     INTEGER NOT NULL REFERENCES clubs(id),\n  student_id  INTEGER NOT NULL,\n  status      TEXT NOT NULL,          -- 'active', 'alumni' or 'pending'\n  PRIMARY KEY (club_id, student_id)\n);\n\n-- clubs\n-- 1 | Chess Club        | 1\n-- 2 | Film Society      | 1\n-- 3 | Robotics          | 1\n-- 4 | Board Game Night  | 0\n\n-- memberships\n-- 1 | 501 | active\n-- 1 | 502 | active\n-- 1 | 503 | alumni\n-- 2 | 504 | pending\n-- 4 | 505 | active\n\n-- Our current query (Film Society and Robotics are missing):\n-- SELECT c.name, COUNT(*) FROM clubs c\n-- JOIN memberships m ON m.club_id = c.id\n-- WHERE m.status = 'active' GROUP BY c.name;","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":10},{"type":"maxProseWords","max":25}],"mistakes":[{"title":"Filtering in WHERE, or the wrong statuses","why":"A WHERE on status drops empty clubs, and the AI can't know pending members count.","fix":"Add: \"Put status IN ('active', 'pending') in the LEFT JOIN's ON clause.\"","checks":["r0"]},{"title":"COUNT(*) on a LEFT JOIN","why":"COUNT(*) counts the empty joined row as 1, so empty clubs show 1.","fix":"Add: \"Count a memberships column, not *.\"","checks":["r0"]},{"title":"Including interest groups","why":"The AI can't know only chartered clubs belong in the app's list.","fix":"Add: \"Only is_chartered = 1.\"","checks":["r1"]},{"title":"Unnamed columns and sort","why":"The AI keeps name and an unnamed count.","fix":"Add: \"Columns exactly club_name, member_count; ORDER BY member_count DESC, club_name.\"","checks":["r2","codeBlocks","maxCodeLines","maxProseWords"]}],"promptHints":[{"label":"Asks for zero-member clubs","patterns":["zero","\\b0\\b","no members","including"]},{"label":"Mentions the join trap","patterns":["left join","on clause","not.{0,20}where"]},{"label":"Limits to chartered clubs","patterns":["chartered"]},{"label":"Names the columns","patterns":["member_count","club_name"]},{"label":"Says which statuses count","patterns":["pending"]},{"label":"Gives the sort","patterns":["order by","highest first","desc"]}],"hint":"'Including zero' is where LEFT JOIN queries go wrong. Tell the AI which clubs and statuses count, where the status filter goes, and the exact columns and order.","rubricLabels":["Uses a LEFT JOIN from clubs to memberships with m.status IN ('active', 'pending') in the ON clause (not WHERE), and counts COUNT(m.club_id) or COUNT(m.student_id), not COUNT(*), so clubs with none show 0","Keeps only clubs with is_chartered = 1 (so Board Game Night is excluded)","Returns exactly club_name and member_count, ordered by member_count descending and then club_name"]}