{"id":"data2-sql-latest-record-per-customer","audience":"analysts","category":"data","track":"data","technique":"constraints","level":"advanced","title":"Write SQL that keeps the latest record per customer","free":false,"task":"A contacts table has several snapshots per customer and you need only the current one. Ask for one Postgres query in a single code block with at most 30 words outside it. Keep the newest non-deleted row per customer_id, break ties by the higher snapshot_id, and return customer_id, email, plan and updated_at. Start the code with the comment line '-- report: current_snapshots'.","materialLabel":"Schema and notes (attached to your prompt automatically)","material":"Schema (Postgres) - Kestrel CRM export\n\ncustomer_snapshots(snapshot_id, customer_id, email, plan, updated_at, is_deleted)\n\nSample rows:\nsnapshot_id | customer_id | email | plan | updated_at | is_deleted\n901 | 17 | ana@alder.example | basic | 2025-09-01 10:00 | false\n902 | 17 | ana@alder.example | pro | 2025-10-05 09:30 | false\n903 | 17 | ana@alder.example | pro | 2025-10-05 09:30 | false\n904 | 22 | lee@birch.example | basic | 2025-08-12 14:00 | false\n905 | 22 | lee@birch.example | basic | 2025-10-20 08:00 | true\n906 | 31 | sam@cedar.example | pro | 2025-10-01 12:00 | false\n\nNotes from the data team:\n- Rows 902 and 903 are exact duplicates (same updated_at); keep the one with the higher snapshot_id.\n- Customer 22's newest snapshot is a deletion marker. Question: should customer 22 appear? Decision: a customer whose newest snapshot is deleted must not appear at all. Do not fall back to their older, undeleted snapshot.\n- The table has about 3 million rows; avoid self-joins on the full table if a window function works.\n- updated_at is a timestamp.","rules":[{"type":"codeBlocks","count":1},{"type":"maxProseWords","max":30}],"mistakes":[{"title":"Filtering deleted too early","why":"The AI adds WHERE is_deleted = false first, so customer 22 returns with the old row.","fix":"Add: \"Rank all snapshots first, then keep rn = 1 AND is_deleted = false.\"","checks":["r0"]},{"title":"No tie-breaker","why":"Two rows with the same timestamp both rank first or the choice is random.","fix":"Add: \"ORDER BY updated_at DESC, snapshot_id DESC.\"","checks":["r1"]},{"title":"Self-joining on max date","why":"The AI uses a join on MAX(updated_at), which returns duplicate rows for ties.","fix":"Add: \"Use ROW_NUMBER in a CTE, no self-join.\"","checks":["r2"]},{"title":"Leaving the format to chance","why":"The AI picks its own length and layout unless told the exact shape.","fix":"Add: \"Put the code in exactly 1 code block. Keep the writing outside the code under 30 words.\"","checks":["codeBlocks","maxProseWords"]}],"promptHints":[{"label":"Names the window function","patterns":["row_number","partition by"]},{"label":"Gives the tie-break","patterns":["snapshot_id desc","tie"]},{"label":"Says the filter order","patterns":["after","first","rn = 1"]},{"label":"Bans the self-join","patterns":["no self.join","cte"]},{"label":"Caps the writing","patterns":["one (short )?sentence","\\d+ words","code block"]}],"hint":"The order of operations matters: pick the newest row first, then drop deleted. Say which comes first.","mission":"Get the latest row per customer in SQL.","musts":["One Postgres query","Tie-break on snapshot_id","Delete filter after ranking"],"rubricLabels":["The query uses ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY updated_at DESC, snapshot_id DESC) so ties on updated_at go to the higher snapshot_id","The is_deleted filter is applied after picking the newest row (rank 1 AND is_deleted = false), not before, so customer 22 does not reappear with the older snapshot","It returns customer_id, email, plan and updated_at, uses a CTE or subquery with rn = 1, and does not self-join the whole table; the first line of the code is the comment -- report: current_snapshots"]}