On your TicketFlow PostgreSQL (psql or Django shell with
connection.cursor()). Do not look at solutions.md before submitting.
Setup: minimal test data in the Django shell (or what you already have from 00b).
Exercise 1 — CTE of repeat buyers
- With a CTE, list users with 3 or more confirmed historical reservations and their count.
- Rewrite it with a subquery in the
FROMwithoutWITH: which version reads better in a review? - Add the total amount spent by each one (second CTE + JOIN).
Exercise 2 — Ranking with a window
- Ranking of events by revenue (
RANK()). What happens if two tie? - Add a column with the previous event's revenue (
LAG()) and the difference. ROW_NUMBER()over(event_id, created_at)of reservations: number each event's reservations by age and keep the first 2 per event (the top-N-per-group pattern).
Exercise 3 — The silent duplication
- Write the "WRONG" query from lesson point 3 on your DB (or simulate it with little data) and demonstrate with a case (1 reservation, 2 items, 1 payment) that
SUM(p.amount)comes out multiplied. - Fix it with separate CTEs and check the correct amount.
Exercise 4 — Availability as the database writes it
- Run the availability query (lesson point 4.1) and compare the result with your Python
available_seats()from 00b. Do they match? - Rewrite it with
LEFT JOIN + IS NULLinstead ofNOT EXISTS. Which one reads clearer to you? - Add the sector and the ordering by row/number, and limit to the first 50 (SQL pagination).
Exercise 5 — Revenue series and conversion
- Run the 30-day revenue query with
generate_seriesand manually insert a payment "from yesterday" to see the day with a non-zero value. - Conversion query per event with
FILTER. Add the "expiration rate" one (expired reservations / created).
Exercise 6 — The organization tree (recursive CTE)
- Write the recursive CTE of the organization tree (§5) with the anti-cycle guard (
depthcolumn,WHERE depth < 20). Verify: a 3-level tree returns sales for every node, root included. - Break the data: insert a cycle (
A → B → A). Run WITHOUT the guard (does the query hang or explode?) and with the guard (does it finish?). Document the evidence of the disaster and of the remedy. - The recursive step's index:
EXPLAINthe query without and with an index onparent_id(Lesson 09). What does each hop cost?
Exercise 7 — The two-grain report
- Rewrite the sales-per-event report with
GROUPING SETS((event), (event, day)) andGROUPING()to label each row with its level. Verify that the event-grain total matches the sum of the event×day grain (the accounting cross-check from 08). - The equivalent naïve query with a subquery (§6's): compare plans (
EXPLAIN ANALYZE) and times. When does each pay off? - Document in 5 lines what each report of your project IS per row (its "grain") — the question this module leaves installed.
Submit
Paste the queries and trimmed outputs. When corrected we close Lesson 07; next up Lesson 08 — Data modeling.