Skip to content
>_sqlbuddy

Orders Gap Analysis

Find the gap in days between consecutive orders per customer.

Start practice

Problem 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_days must be NULL (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_date may be NULL; such an order has an unknown date and its gap must be NULL.
  • The output must include at least: customer_id, order_date, and gap_days.

In SQLite, the number of days between two dates is CAST(julianday(later) - julianday(earlier) AS INTEGER).

Example

idcustomer_idorder_date
112024-01-10
212024-01-13
322024-01-12

Expected result (row order doesn't matter):

idcustomer_idorder_dategap_days
112024-01-10NULL
212024-01-133
322024-01-12NULL

Constraints

  • orders.id is the primary key.
  • orders.order_date is nullable.

Tips

  • LAG() is the natural tool here; it produces NULL for the first row in each partition.
  • The order used by LAG must be deterministic — order by order_date, then by id as a tiebreaker.
  • A NULL order date in the ORDER BY sorts 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

Learn more