The request

From Laura Bennett, Head of Finance
Your goal
Step 1 of 3. Check the months. For orders placed from September 1 to December 31, 2025, return month, orders (all orders), completed, cancelled, refunded and pending (orders with each status). Sort by month.
- Read from the
orderstablenot done yet - Show exactly
monthorderscompletedcancelledrefundedpendingnot done yet - 4 rows, sorted as askednot done yet
Step 2 of 3. Build the KPI table for 2024-11, 2025-10 and 2025-11. Return month, net_revenue (rounded to 2), orders (distinct completed orders with a counted line), avg_order_value (revenue / orders, rounded to 2), buyers (distinct customers who ordered), new_buyers (buyers whose first completed order, ever, falls in that month), returning_buyers (buyers - new_buyers), refunds (refund_amount from returns, by the month of returned_on, rounded to 2) and web_conversion_pct (converted sessions * 100 / all sessions that month, by started_at, rounded to 2). Sort by month.
- Read from the
orderstablenot done yet - Read from the
order_itemstablenot done yet - Show exactly
monthnet_revenueordersavg_order_valuebuyersnew_buyersreturning_buyersrefundsweb_conversion_pctnot done yet
Step 3 of 3. Explain the year-over-year gap. For completed orders (lines with quantity > 0) in 2024-11 and 2025-11, total each order's net revenue, then label it size_band 'large' if that total is 5000 or more, else 'regular'. Return month, size_band, orders, net_revenue (rounded to 2) and avg_order_value (rounded to 2). Sort by month, then size_band.
- Read from the
orderstablenot done yet - Read from the
order_itemstablenot done yet - Show exactly
monthsize_bandordersnet_revenueavg_order_valuenot done yet
This case unlocks when you finish any one of:
The ticket and lesson are open to read now. Solve every level in one of those chapters, in whichever track you prefer, and this case opens.
Step 1 · your query
Loading the editor…
Reference solution
| order_id | customer_id | order_date | status | channel |
|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace |
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
Step 2 · your query
Loading the editor…
Reference solution
| order_id | customer_id | order_date | status | channel |
|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace |
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
Step 3 · your query
Loading the editor…
Reference solution
| order_id | customer_id | order_date | status | channel |
|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace |
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
What Laura gets, and why
Tables
Harbor & Pine store data, ready to query.
orders12,000 rows · 7 columns
order_idintegercustomer_idintegerorder_datetimestampstatusvarcharchannelvarcharshipping_feedecimalcoupon_codevarchar
| order_id | customer_id | order_date | status | channel | shipping_fee | coupon_code |
|---|---|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web | 0.00 | NULL |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web | 0.00 | NULL |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace | 4.99 | WELCOME10 |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace | 4.99 | WELCOME10 |
| 1005 | 82 | 2023-01-02 11:43:36 | completed | web | 0.00 | WELCOME10 |
order_items30,338 rows · 6 columns
order_item_idintegerorder_idintegerproduct_idintegerquantityintegerunit_pricedecimaldiscount_pctdecimal
| order_item_id | order_id | product_id | quantity | unit_price | discount_pct |
|---|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 | 0.00 |
| 2 | 1001 | 154 | 3 | 11.99 | 0.00 |
| 3 | 1002 | 154 | 4 | 11.99 | 0.00 |
| 4 | 1002 | 194 | 1 | 149.00 | 0.00 |
| 5 | 1002 | 193 | 2 | 19.99 | 0.00 |
returns1,673 rows · 5 columns
return_idintegerorder_item_idintegerreturned_ondatereasonvarcharrefund_amountdecimal
| return_id | order_item_id | returned_on | reason | refund_amount |
|---|---|---|---|---|
| 1 | 14 | 2023-01-10 | damaged | 83.69 |
| 2 | 42 | 2023-01-10 | wrong_item | 19.99 |
| 3 | 105 | 2023-01-14 | wrong_item | 10.99 |
| 4 | 24 | 2023-01-16 | changed_mind | 26.99 |
| 5 | 126 | 2023-01-16 | late | 20.99 |
web_sessions40,000 rows · 7 columns
session_idintegercustomer_idintegerstarted_attimestampdevicevarcharsourcevarcharpages_viewedintegerconvertedboolean
| session_id | customer_id | started_at | device | source | pages_viewed | converted |
|---|---|---|---|---|---|---|
| 1 | NULL | 2023-01-01 23:02:24 | mobile | paid | 1 | false |
| 2 | 18 | 2023-01-01 15:07:49 | desktop | paid | 1 | false |
| 3 | NULL | 2023-01-01 16:55:46 | desktop | direct | 7 | false |
| 4 | NULL | 2023-01-01 12:43:28 | mobile | organic | 3 | false |
| 5 | NULL | 2023-01-01 13:06:21 | mobile | social | 2 | false |
customers2,018 rows · 9 columns
customer_idintegerfirst_namevarcharlast_namevarcharemailvarcharcityvarcharstatevarcharsignup_datedatesegmentvarcharreferral_sourcevarchar
| customer_id | first_name | last_name | city | state | signup_date | segment | referral_source | |
|---|---|---|---|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco | CA | 2022-06-02 | consumer | search |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta | GA | 2022-06-02 | consumer | NULL |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles | CA | 2022-06-04 | business | NULL |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle | WA | 2022-06-06 | business | |
| 5 | Kyle | Jimenez | kjimenez27@yahoo.com | Indianapolis | IN | 2022-06-07 | consumer | NULL |
products120 rows · 8 columns
product_idintegernamevarcharcategoryvarcharsubcategoryvarcharunit_pricedecimalunit_costdecimallaunched_ondateis_activeboolean
| product_id | name | category | subcategory | unit_price | unit_cost | launched_on | is_active |
|---|---|---|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 | NULL | 2023-09-11 | true |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 | 503.50 | 2024-05-16 | true |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 | 429.87 | 2023-05-27 | true |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 | 214.70 | 2022-12-20 | true |
| 105 | Avery Leather Bed Frame | Furniture | Beds | 449.00 | 232.70 | 2021-08-31 | true |
employees60 rows · 8 columns
employee_idintegerfirst_namevarcharlast_namevarchardepartmentvarchartitlevarcharmanager_idintegerhire_datedatesalaryinteger
| employee_id | first_name | last_name | department | title | manager_id | hire_date | salary |
|---|---|---|---|---|---|---|---|
| 1 | Catherine | Hale | Executive | Chief Executive Officer | NULL | 2016-03-01 | 285000 |
| 2 | Robert | Kim | Executive | Chief Operating Officer | 1 | 2017-01-09 | 235000 |
| 3 | Megan | Collins | Sales | Head of Sales | 1 | 2018-04-16 | 172000 |
| 4 | Chloe | Gutierrez | Sales | Account Executive | 3 | 2020-01-21 | 72000 |
| 5 | Frank | Bell | Sales | Account Executive | 3 | 2023-05-21 | 73000 |
marketing_spend3,276 rows · 3 columns
spend_datedatechannelvarcharamountdecimal
| spend_date | channel | amount |
|---|---|---|
| 2023-01-01 | paid | 492.99 |
| 2023-01-01 | 37.38 | |
| 2023-01-01 | social | 200.53 |
| 2023-01-02 | paid | 709.13 |
| 2023-01-02 | 64.13 |
The lesson
What you are checking, and why
A month is ready to report only when its orders have settled. Orders arrive as pending and become
completed, cancelled or refunded over the following days. Counting statuses per month shows
where the open orders sit, using the same conditional-count pattern as any pivot:
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending
November has 2 pending orders out of 715; December has 94 out of 777. That is the evidence behind reporting November.
One CTE per source
The KPIs come from three tables at three grains: order lines, returns and web sessions. The safe pattern is to bring each to one row per month in its own CTE, then join the CTEs on month:
sales AS (... FROM lines ... GROUP BY month),
refunds AS (... FROM returns GROUP BY month),
web AS (... FROM web_sessions GROUP BY month)
New buyers need one more step. “New” means the customer’s first completed order falls in the
month, so a firsts CTE finds MIN(order_date) per customer, and the sales CTE counts the buyers
whose first order month equals the order month. Returning buyers are the rest.
Reading the result
| month | net_revenue | orders | avg_order_value | buyers | web_conversion_pct |
|---|---|---|---|---|---|
| 2024-11 | 319,297.22 | 564 | 566.13 | 357 | 3.50 |
| 2025-10 | 174,599.43 | 333 | 524.32 | 261 | 2.33 |
| 2025-11 | 292,364.40 | 651 | 449.10 | 442 | 4.45 |
Against October everything is up, as it is every November. Against last year, volume grew and revenue fell, so the question becomes average order value. Step 3 answers it: seven bulk orders last November, one this November.
Explaining the mover
Step 3 works at the order level, because the size of an order is only known once its lines are
added up. A CTE totals each order, the outer query labels it with CASE WHEN and groups the orders
by month and band. The result splits each November into a few large orders and many regular ones,
which is the breakdown that turns “revenue fell” into a reason leadership can act on.
Pitfalls
strftimeon a timestamp works the same as on a date, soreturned_onandorder_dategive the same'YYYY-MM'labels and the CTEs join cleanly.COUNT(DISTINCT customer_id)per month counts buyers; summing buyers across months double counts people who bought in both.- Labelling order size on lines rather than orders puts big orders in the wrong band.
Lantern lit!
Practised: data validationcteconditional aggregationcount distinctkpi definitionmomyoy
- Solved
- No hints
- First run
