Orders Gap Analysis
Find the gap in days between consecutive orders per customer.
Start practiceProblem statement
Prompt
Given the orders table below, write a query that returns one row per order, with an extra column showing how many days elapsed since that customer's previous order.
- The column must be named
gap_days. - The first order for each customer has no previous order:
gap_daysmust beNULL(not 0). - Orders are compared per customer — a customer's order is only compared with that same customer's earlier orders.
- If two orders share the same date, the gap between them is 0 days.
orders.order_datemay beNULL; such an order has an unknown date and its gap must beNULL.- The output must include at least:
customer_id,order_date, andgap_days.
In SQLite, the number of days between two dates is CAST(julianday(later) - julianday(earlier) AS INTEGER).
Example
| id | customer_id | order_date |
|---|---|---|
| 1 | 1 | 2024-01-10 |
| 2 | 1 | 2024-01-13 |
| 3 | 2 | 2024-01-12 |
Expected result (row order doesn't matter):
| id | customer_id | order_date | gap_days |
|---|---|---|---|
| 1 | 1 | 2024-01-10 | NULL |
| 2 | 1 | 2024-01-13 | 3 |
| 3 | 2 | 2024-01-12 | NULL |
Constraints
orders.idis the primary key.orders.order_dateis nullable.
Tips
LAG()is the natural tool here; it producesNULLfor the first row in each partition.- The order used by
LAGmust be deterministic — order byorder_date, then byidas a tiebreaker. - A
NULLorder date in theORDER BYsorts last in SQLite, which is exactly the "unknown" behavior we want.
Schema
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL,
order_date DATE -- NULL allowed
);
Sample data
INSERT INTO orders (id, customer_id, order_date) VALUES
(1, 1, '2024-01-10'),
(2, 1, '2024-01-13'),
(3, 1, '2024-01-20'),
(4, 2, '2024-01-12'),
(5, 2, '2024-02-01'),
(6, 3, '2024-03-05');
Additional hidden fixtures are applied during validation to test edge cases.
Solution
One correct approach — try solving it yourself in the practice editor first, then compare. There is usually more than one valid solution.
-- Reference: gap in days since the customer's previous order, NULL when first/unknown.
WITH ordered AS (
SELECT id, customer_id, order_date,
LAG(order_date) OVER (
PARTITION BY customer_id
ORDER BY order_date, id
) AS prev_order_date
FROM orders
)
SELECT id, customer_id, order_date,
CAST(julianday(order_date) - julianday(prev_order_date) AS INTEGER) AS gap_days
FROM ordered
ORDER BY id;
Key concepts
- WITH
- LAG
- julianday
- CAST
- Subqueries
Related questions
- mediumConsecutive Login DaysFind users who logged in on three or more consecutive calendar days.
- mediumFirst and Last Order Per CustomerShow the date of each customer's first and last order.
- mediumGame Play Analysis IVFind the fraction of players who logged in the day after their first login.
- mediumMonthly Sales RankingRank salespeople by their monthly sales, including ties, and handle months with no sales.
- mediumNth Highest SalaryReturn the third-highest distinct salary, or NULL when it does not exist.