Amazon-style Company ChallengeHardVerified answerSQLite live

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_idINTEGER
  • product_nameVARCHAR(200)
  • categoryVARCHAR(100)
  • stock_quantityINTEGER
  • warehouse_idINTEGER

warehouses

  • warehouse_idINTEGER
  • locationVARCHAR(100)

order_items

  • product_idINTEGER
  • quantityINTEGER
  • priceREAL

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_namecategorywarehouse_locationcurrent_stockavg_daily_salesdays_remainingpotential_revenue_lossrestock_rank
Python Programming BookBooksDallas, TX1500.13120039.991
Coffee MakerHome & KitchenLos Angeles, CA2000.25800159.982
Bluetooth SpeakerElectronicsSeattle, WA2500.38666.7179.973
Laptop StandElectronicsSeattle, WA3000.25120091.984
Desk LampHome & KitchenLos Angeles, CA4000.13320034.995

Learn the concepts behind this answer

Strengthen your understanding with these targeted learning topics:

Continue practicing

SQL Interview Practice

Return to the complete interview preparation experience.