Product Replenishment Priority Analysis
Show the top 5 products most at risk of stockout — ranked by lowest stock first, then highest sales volume as a tiebreaker. Include estimated days of inventory remaining and revenue at risk.
- CTEs
- Window functions
- Joins
- Subqueries
- Aggregation
Challenge brief
Understand the request
Supply Chain Team needs to prioritize which products to restock first based on current inventory levels and recent sales velocity.
Identify the top 5 stockout-risk products using a CTE for sales velocity and a window function for priority ranking.
Return
- product_name
- category
- warehouse_location
- current_stock
- avg_daily_sales (total sold / 8 days, rounded to 2 decimals)
- days_remaining (current_stock / avg_daily_sales, rounded to 1 decimal; 999 if never sold)
- potential_revenue_loss (revenue from order history, rounded to 2 decimals)
- restock_rank
Constraints
- Average daily sales uses the fixture's eight-day observation window
- Products with no sales remain eligible and display zero sales and revenue
- Prioritize lower stock, then higher sales volume, then lower product ID
- Return exactly five products with unique priority positions
Data you will use
Review the relevant tables before deciding how to join, filter, or aggregate them.
products
product_idINTEGERproduct_nameVARCHAR(200)categoryVARCHAR(100)stock_quantityINTEGERwarehouse_idINTEGER
warehouses
warehouse_idINTEGERlocationVARCHAR(100)
order_items
product_idINTEGERquantityINTEGERpriceREAL
Hints, when you need them
Open one clue at a time so you still do the reasoning.
Hint 1
Break this into two steps. Step 1 — CTE: aggregate total units sold and revenue per product from order_items. Step 2 — Main query: join products and warehouses, LEFT JOIN the CTE (some products may have no sales), compute avg_daily_sales and days_remaining, then rank by stock ASC.
Hint 2
Aggregate total units and revenue per product first. In the inventory query, use null-safe calculations and assign ROW_NUMBER by stock ascending, sales descending, then product ID.
Hint 3
Scaffold: WITH sales_data AS (... one row per product ...) join inventory, calculate null-safe rates, assign a deterministic priority position, and retain five rows.
Verified SQL answer
Attempt the problem first, then compare structure and reasoning—not just syntax.
Reveal solution and explanation
WITH sales_data AS (SELECT oi.product_id, SUM(oi.quantity) AS total_sold, SUM(oi.price * oi.quantity) AS revenue FROM order_items oi GROUP BY oi.product_id) SELECT p.product_name, p.category, w.location AS warehouse_location, p.stock_quantity AS current_stock, COALESCE(ROUND(sd.total_sold / 8.0, 2), 0) AS avg_daily_sales, CASE WHEN COALESCE(sd.total_sold, 0) > 0 THEN ROUND(p.stock_quantity * 1.0 / (sd.total_sold / 8.0), 1) ELSE 999 END AS days_remaining, COALESCE(ROUND(sd.revenue, 2), 0) AS potential_revenue_loss, ROW_NUMBER() OVER (ORDER BY p.stock_quantity ASC, COALESCE(sd.total_sold, 0) DESC, p.product_id ASC) AS restock_rank FROM products p INNER JOIN warehouses w ON p.warehouse_id = w.warehouse_id LEFT JOIN sales_data sd ON p.product_id = sd.product_id ORDER BY restock_rank LIMIT 5;Why this works
The CTE produces one sales row per product before joining inventory. The outer join retains products with no sales, while COALESCE supplies display-safe zeroes. ROW_NUMBER uses stock, sales, and product ID for a deterministic priority order. The 8.0 divisor represents the fixture's stated eight-day observation window.
Success check
Top 5 products starting with Python Programming Book (rank 1, 150 stock, 1200 days remaining)
Expected result
Use this output to verify values, aliases, ordering, and row count.
| product_name | category | warehouse_location | current_stock | avg_daily_sales | days_remaining | potential_revenue_loss | restock_rank |
|---|---|---|---|---|---|---|---|
| Python Programming Book | Books | Dallas, TX | 150 | 0.13 | 1200 | 39.99 | 1 |
| Coffee Maker | Home & Kitchen | Los Angeles, CA | 200 | 0.25 | 800 | 159.98 | 2 |
| Bluetooth Speaker | Electronics | Seattle, WA | 250 | 0.38 | 666.7 | 179.97 | 3 |
| Laptop Stand | Electronics | Seattle, WA | 300 | 0.25 | 1200 | 91.98 | 4 |
| Desk Lamp | Home & Kitchen | Los Angeles, CA | 400 | 0.13 | 3200 | 34.99 | 5 |
Learn the concepts behind this answer
Strengthen your understanding with these targeted learning topics:
Continue practicing
Explore related company challenges
Airbnb
Independent Airbnb-style marketplace, booking, listing, payment, review, and guest analytics SQL practice.
Uber
Independent Uber-style mobility marketplace SQL practice covering trips, drivers, riders, pricing, payments, and promotions.
Microsoft
Independent Microsoft-style cloud, productivity, subscription, usage, support, and customer analytics SQL practice.
Return to the complete interview preparation experience.