ExpertCTEs & Recursion50 points

Black Friday month: the 7-day rolling average

November is the peak of the shopping year, but many days have no sales at all, and a naive GROUP BY simply skips them. The pricing team wants a smooth view: net revenue per calendar day of November 2025 (zero on days without sales) and the average of the current day and the 6 days before it. Table notes: a line's net revenue is quantity * unit_price * (1 - discount_pct / 100.0). Orders with status Cancelled never count as sales.

Task: build a calendar with a recursive CTE starting at 2025-10-25 (so that early November has a full 7-day window) up to 2025-11-30, left join daily revenue, and return only November days as day, revenue (0 when no sales) and avg_7d (trailing 7-day average including today, counting zero days). Use ROUND(x, 2) on both numbers. Sort by day, oldest first.

The data you can query

Each table is shown with its column types and the first rows, so you can see exactly what the data looks like.

customers48 rows
id INTEGERname TEXTcountry TEXTcity TEXTsignup_date TEXTloyalty_tier TEXT
1Emily CarterUnited StatesAustin2025-01-11NULL
2Michael BrooksUnited StatesSeattle2025-01-19Silver
3Sofia RamirezUnited StatesMiami2025-08-21Gold
4Jake TurnerUnited StatesChicago2025-03-21Bronze
5Oliver HughesUnited KingdomManchester2025-03-22Bronze
6Amelia WrightUnited KingdomLondon2025-10-14Platinum

Showing the first 6 of 48 rows.

order_items719 rows
id INTEGERorder_id INTEGERproduct_id INTEGERquantity INTEGERunit_price REALdiscount_pct INTEGER
1115394.950
2110224.990
322112920
4315394.9515
5424112.9910
64211290

Showing the first 6 of 719 rows.

orders340 rows
id INTEGERcustomer_id INTEGERorder_date TEXTship_date TEXTdelivered_date TEXTstatus TEXTchannel TEXT
112025-01-162025-01-192025-01-21DeliveredMobile App
212025-01-232025-01-252025-01-30DeliveredWeb
312025-01-232025-01-252025-01-29DeliveredWeb
422025-01-312025-02-022025-02-04DeliveredWeb
512025-02-022025-02-032025-02-06DeliveredSocial Media
6312025-02-142025-02-152025-02-20DeliveredWeb

Showing the first 6 of 340 rows.

payments329 rows
id INTEGERorder_id INTEGERmethod TEXTamount REAL
11PayPal334.83
22PayPal23.2
33Card242.12
44Card40.69
55Card148.14
66Gift Card42.95

Showing the first 6 of 329 rows.

products36 rows
id INTEGERname TEXTcategory TEXTseller_id INTEGERprice REALcost REAL
1Noise-Cancelling HeadphonesElectronics8129.9971
2Smart Fitness WatchElectronics789.548
3Portable Power Bank 20000mAhElectronics834.9917
44K Action CameraElectronics115996
5USB-C Charging HubElectronics627.511
6Wireless Gaming MouseElectronics145.9922

Showing the first 6 of 36 rows.

returns52 rows
id INTEGERorder_item_id INTEGERreturn_date TEXTreason TEXTrefund_amount REAL
172025-02-10Wrong size18.99
2312025-04-12Not as described34.99
3392025-04-06Wrong size31.05
4502025-05-09Changed my mind169
5692025-05-27Arrived late34.99
6742025-06-02Arrived late23.92

Showing the first 6 of 52 rows.

reviews261 rows
id INTEGERorder_item_id INTEGERrating INTEGERcomment_length INTEGERreview_date TEXT
112NULL2025-01-22
2242322025-02-02
374182025-02-16
41252552025-03-14
51511612025-03-15
61742082025-03-19

Showing the first 6 of 261 rows.

sellers10 rows
id INTEGERname TEXTcountry TEXTjoined_date TEXT
1Northwind TradersUnited States2024-06-14
2Brightside GoodsUnited Kingdom2024-09-02
3Kaufhaus BerlinGermany2024-11-20
4Maison PetiteFrance2025-01-15
5Rio BazaarBrazil2024-08-08
6Bharat EmporiumIndia2024-07-19

Showing the first 6 of 10 rows.

Your query runs on SQLite. Write a single SELECT; use LIMIT instead of TOP.

Need a hint?

date(d, '+1 day') walks the calendar. Filter to November only in the last step, after the window function has seen October's days.