lesson 75 Warehouse & reporting projects · advanced
Customer & product reporting contracts
Produce customer and product reports at a defined level of detail.
the idea
A reusable report combines identity, totals, dates, and meaningful segmentation at one entity grain. Preserve entities with no sales when requested. These exercises define recency against 2025-04-01 rather than today, so the answer is reproducible.
tables in this lesson
The challenges use this data. Each column shows its type underneath; → marks a link to another table.
dim_customer4 columns · 5 rows
| customer_keyinteger · key | customer_idtext | nametext | countrytext |
|---|---|---|---|
| 1 | C001 | Alice Nguyen | United States |
| 2 | C002 | Ben | United Kingdom |
| 3 | C003 | Cara | United Kingdom |
| 4 | C004 | Dev | India |
| 5 | C005 | Elena | Canada |
all 5 rows
fact_sales6 columns · 9 rows
| sale_keyinteger · key | customer_keyinteger | product_keyinteger | quantityinteger | salesreal | order_datetext |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2 | 24 | 2025-01-01 |
| 2 | 2 | 3 | 1 | 80 | 2025-01-02 |
| 3 | 1 | 2 | 1 | 45 | 2025-01-15 |
| 4 | 3 | 4 | 2 | 240 | 2025-02-01 |
| 5 | 4 | 3 | 2 | 160 | 2025-02-05 |
showing 5 of 9 rows
dim_product5 columns · 4 rows
| product_keyinteger · key | product_idtext | nametext | categorytext | pricereal |
|---|---|---|---|---|
| 1 | P01 | Notebook | Stationery | 12 |
| 2 | P02 | Desk lamp | Home | 45 |
| 3 | P03 | Keyboard | Tech | 80 |
| 4 | P04 | Headphones | Tech | 120 |
all 4 rows
example
The idea in one query. Press Run to see what it returns; running examples never affects your progress.
SELECT c.customer_id, c.name, COUNT(f.sale_key) AS sales_lines, COALESCE(SUM(f.sales),0) AS total_sales FROM dim_customer c LEFT JOIN fact_sales f ON f.customer_key=c.customer_key GROUP BY c.customer_key,c.customer_id,c.name;
Watch for: These are report contracts, not inferred customer lifetime value. Segmentation thresholds are exercise-specific.
build it step by step
Each step changes one thing. Run them in order and watch the result change.
Start from the customer. Customers with no sales still belong on this report. The sales table alone cannot list them.
step-1.sqlSELECT customer_key, customer_id, name FROM dim_customer;
Run the reference. A reusable report combines identity, totals, dates, and meaningful segmentation at one entity grain. Preserve entities with no sales when requested. These exercises define recency against 2025-04-01 rather than today, so the answer is reproducible.
step-2.sqlSELECT c.customer_id, c.name, COUNT(f.sale_key) AS sales_lines, COALESCE(SUM(f.sales),0) AS total_sales FROM dim_customer c LEFT JOIN fact_sales f ON f.customer_key=c.customer_key GROUP BY c.customer_key,c.customer_id,c.name;