Average Spending by Account Status

A medium SQL interview practice problem on DataDriven. Write the query and run it against a real database, with instant feedback.

Domain
SQL
Difficulty
medium
Seniority
L3
Asked in
Rockerbox

Problem

Users who never made a purchase stay out of finance's lifetime value comparison, which weighs account statuses against each other only across actual buyers. Using the users and transactions tables, show each account status with the average lifetime spend of its buyers, a buyer's lifetime spend being everything they have paid across all of their transactions.

Average per-user lifetime spending segmented by account status

Tables

users

Columns: user_id INTEGER, username TEXT, email TEXT, signup_date TEXT, account_status TEXT, age_bucket TEXT

users: 10 of 200 rows
user_idusernameemailsignup_dateaccount_statusage_bucket
100alicealice@example.com2025-02-02inactive25-34
197aaron42aaron42@example.com2026-03-03suspended35-44
294 ameliaamelia@example.com2024-04-04pending_verification45-54
391arjun arjun@example.com2025-05-05active55-64
488ava99ava99@example.com2026-06-06inactive65+
585andrew_kandrew_k@example.com2024-07-07suspendedNULL
682anikaanika@example.com2025-08-08 16:34:00pending_verification18-24
779aidenaiden@example.com2026-09-09 14:53:00active25-34
876aria_baria_b@example.com2024-10-10inactive35-44
973brianbrian@example.com2025-11-11suspended45-54

transactions

Columns: transaction_id INTEGER, user_id INTEGER, product_id INTEGER, quantity INTEGER, total_amount REAL, transaction_date TEXT

transactions: 10 of 200 rows
transaction_iduser_idproduct_idquantitytotal_amounttransaction_date
10671971001223.462026-02-02
11342941050336.932026-03-03
12013911099450.42026-04-04
12684881148563.872026-05-05
13355851197002026-06-06
14026821246290.812026-07-07
146977912953104.282026-08-08
153687613444117.752026-09-09
160397313935-452026-01-10
1670107014421144.692026-02-11

Expected output

First 4 of 4 rows
account_statusavg_total_spending
active9032.38
inactive9060.48
pending_verification9429.165
suspended9183.93

Worked solution and explanation

Why this problem exists in real interviews

LTV questions like this probe one habit specifically: do you name the unit of observation before writing SQL? Finance wants average spend per user, not per transaction. A whale with 1000 small purchases otherwise dominates a casual buyer with one big one. The interviewer is watching to see if you collapse to per-user totals in a subquery before averaging.


Break down the requirements

Step 1: Collapse transactions to one row per user

Subquery on transactions with SUM(total_amount) AS total_spent GROUP BY user_id. This is the unit of observation the outer average should run over. Pre-aggregating here is what makes the final AVG user-weighted instead of transaction-weighted.

Step 2: Join to users for the segment column

INNER JOIN users u ON u.user_id = ut.user_id. Inner join is intentional: the statement keeps users who never made a purchase out of the comparison, so zero-spenders are out of the denominator. Pull u.account_status only; you do not need any other user column.

Step 3: Aggregate up to account_status

Outer SELECT u.account_status, AVG(ut.total_spent) GROUP BY u.account_status. Each user contributes exactly one number to the bucket regardless of whether they ran 1 transaction or 1,000. That is the user-weighted lifetime spend finance asked for.


The solution

USER-WEIGHTED AVG VIA PRE-AGGREGATION
SELECT
  u.account_status,
  AVG(user_totals.total_spent) AS avg_total_spending
FROM users u
INNER JOIN (
  SELECT user_id, SUM(total_amount) AS total_spent
  FROM transactions
  GROUP BY user_id
) user_totals
  ON u.user_id = user_totals.user_id
GROUP BY u.account_status;
Wrong, transaction-weighted
SELECT u.account_status, AVG(t.total_amount) FROM users u JOIN transactions t ... One power user with 1,000 purchases of $5 and one casual user with a single $5,000 purchase. Direct AVG(total_amount) = ($5,000 + $5,000) / 1,001 = $9.99. The power user's behavior dominates the bucket.
Right, user-weighted
Subquery collapses to two rows: $5,000 and $5,000. Outer AVG = $5,000. Both users count once. That is what the finance team means by average spend per user in an LTV model.

COMMON FOLLOW-UP QUESTIONS

Common follow-up questions