Claude Opus 4.6
Unrated11,787ms602 tokens
```sql
SELECT
c.name,
SUM(o.amount) AS total_spend
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE o.created_at >= '2024-01-01'
AND o.created_at < '2025-01-01'
GROUP BY c.id, c.name
HAVING COUNT(DISTINCT EXTRACT(MONTH FROM o.created_at)) = 12
ORDER BY total_spend DESC;
```
## How It Works
### Step-by-step breakdown:
1. **JOIN** `customers` with `orders` to link each order to its customer.
2. **WHERE** clause filters orders to only those within the year 2024. Using `>= '2024-01-01'` and `< '2025-01-01'` is index-friendly and avoids edge cases with timestamps (e.g., `2024-12-31 23:59:59` wouldn't be missed).
3. **GROUP BY** `c.id, c.name` aggregates all 2024 orders per customer. Including `c.id` ensures correctness if two customers share the same name.
4. **HAVING** clause is the core filter:
- `EXTRACT(MONTH FROM o.created_at)` pulls the month number (1–12)
- `COUNT(DISTINCT ...)` counts how many *unique* months the customer ordered in
- `= 12` ensures they purchased in **all 12 months**
5. **SUM(o.amount)** calculates total 2024 spend.
6. **ORDER BY total_spend DESC** ranks the most valuable customers first.
### Example result:
| name | total_spend |
|---------------|-------------|
| Alice Johnson | 15,240.00 |
| Bob Smith | 9,870.50 |
| Carol White | 7,330.25 |
### Edge case note:
If `created_at` is a `DATE` type rather than `TIMESTAMP`, the query works identically. If it includes timezone info (`TIMESTAMPTZ`), the `EXTRACT` function operates on the session timezone — consider using `AT TIME ZONE` if timezone precision matters.