Compute a Rolling Seven-Day Revenue Sum with Missing Dates
AmazonData Scientist · Technical ScreenLast updated
Tests the ability to write a PostgreSQL query that generates a continuous daily time series per seller, handles missing sales dates, filters by order status, and computes a rolling 7-day revenue sum.
Problem Statement
You are working on Amazon's Marketplace Analytics team. The team wants to monitor seller revenue trajectories by tracking daily sales and a rolling 7-day revenue sum for each seller.
You are provided with an orders table:
CREATE TABLE orders (
order_id INT PRIMARY KEY,
seller_id VARCHAR(50) NOT NULL,
order_timestamp TIMESTAMPTZ NOT NULL,
order_status VARCHAR(20) NOT NULL,
order_amount NUMERIC(10, 2) NOT NULL
);
Write a PostgreSQL query that calculates the daily revenue and rolling 7-day revenue for each seller under the following rules:
- Status filter: Include only orders where
order_status = 'completed'. - Time zone: Truncate all timestamps to the UTC calendar date (
order_date). - Continuous date spine: For each seller, generate a complete daily sequence of dates starting from the date of their first completed order up to the date of their last completed order (inclusive). If a seller had no completed orders on a given date, output
0.00fordaily_revenue. - Rolling 7-day window: Compute
rolling_7d_revenueas the sum ofdaily_revenuefor the current date and the preceding 6 calendar days. If fewer than 6 preceding days exist in the seller's history, sum all available days up to that point. - Format & Ordering: Round both
daily_revenueandrolling_7d_revenueto 2 decimal places. Sort the output byseller_id ASC,order_date ASC.
Example
Input: orders
| order_id | seller_id | order_timestamp | order_status | order_amount |
|---|---|---|---|---|
| 1 | S1 | 2024-03-01 10:15:00+00 | completed | 100.00 |
| 2 | S1 | 2024-03-01 14:00:00+00 | cancelled | 50.00 |
| 3 | S1 | 2024-03-03 09:30:00+00 | completed | 200.00 |
| 4 | S1 | 2024-03-04 18:00:00+00 | completed | 50.00 |
Output
| seller_id | order_date | daily_revenue | rolling_7d_revenue |
|---|---|---|---|
| S1 | 2024-03-01 | 100.00 | 100.00 |
| S1 | 2024-03-02 | 0.00 | 100.00 |
| S1 | 2024-03-03 | 200.00 | 300.00 |
| S1 | 2024-03-04 | 50.00 | 350.00 |
Explanation: 2024-03-02 had no completed orders, so daily_revenue is 0.00. The rolling 7-day sum on 2024-03-04 covers March 1 through March 4 (100.00 + 0.00 + 200.00 + 50.00 = 350.00).
Hints
Hint 1
First aggregate completed orders by `seller_id` and UTC date, determining each seller's minimum and maximum sale dates.
Hint 2
Use PostgreSQL's `generate_series` inside a lateral join or cross-joined calendar spine to construct every date between each seller's min and max date.
Hint 3
Once the date sequence is fully populated with zero-filled gaps, use the window frame `ROWS BETWEEN 6 PRECEDING AND CURRENT ROW` to calculate the rolling 7-day sum.
Follow-up questions
- How would you modify the query if the observation window must extend to `CURRENT_DATE` for all sellers rather than each seller's last sale date?
- If the table contains hundreds of millions of rows across millions of sellers, what indexes would you create, and how might you optimize the calendar-spine generation?
- How does the behavior of `ROWS BETWEEN 6 PRECEDING AND CURRENT ROW` differ from `RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT ROW` if dates are missing?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.