SQL Quest

Lessons, hints, explained solutions, the in-browser PostgreSQL editor and practice answer checks in your browser are available. Graded assessments, recorded progress from answer checks and new certificates aren't available yet.

Mizan Cloud SaaS

Mizan Cloud (fictional) · 7 tables · 67,088 rows · version 1

Open in the playground

About 600 customer accounts that signed up between January 2023 and December 2025, their users, every subscription row (trials, paid plans, upgrades, downgrades, cancellations and reactivations), invoices, roughly 50,000 product events and support tickets. Built for cohort retention, churn, MRR, funnel and product-usage analysis. Amounts are in SAR.

The documentation is open to everyone. Querying this dataset in the playground is included with Formula Quest membership; lessons that use it follow their own access.

Relationships

plans5PKplan_idplan_nameplan_rankmonthly_priceannual_priceseat_limitis_activeaccounts605PKaccount_idaccount_nameindustrycompany_sizecitycountrycreated_atacquisition_channelis_test_accountusers2,804PKuser_idFKaccount_idfull_nameemailrolecreated_atdeactivated_atlast_seen_atsubscriptions989PKsubscription_idFKaccount_idFKplan_idis_trialbilling_cycleseatsmrrstarted_atended_at+ 2 more columnsinvoices2,885PKinvoice_idFKsubscription_idissued_ondue_onperiod_startperiod_endamountstatuspaid_onevents58,595PKevent_idFKuser_idFKaccount_idevent_nameoccurred_atsupport_tickets1,205PKticket_idFKaccount_idFKopened_by_user_idopened_atfirst_response_atclosed_atprioritycategorysatisfaction_score
Arrows point from a foreign key to the table it references. PK = primary key, FK = foreign key. Numbers are row counts.

Sample queries

Monthly signups by acquisition channel (excluding test accounts)
SELECT date_trunc('month', created_at)::date AS signup_month,
       acquisition_channel,
       count(*) AS accounts
FROM accounts
WHERE NOT is_test_account
GROUP BY 1, 2
ORDER BY 1, 2;
MRR on the last day of 2025 by plan
SELECT p.plan_name, count(*) AS subscriptions, sum(s.mrr) AS mrr
FROM subscriptions s
JOIN plans p ON p.plan_id = s.plan_id
JOIN accounts a ON a.account_id = s.account_id
WHERE NOT a.is_test_account
  AND NOT s.is_trial
  AND s.started_at <= DATE '2025-12-31'
  AND (s.ended_at IS NULL OR s.ended_at > DATE '2025-12-31')
GROUP BY p.plan_name
ORDER BY mrr DESC;
Trial conversion rate by channel
SELECT a.acquisition_channel,
       count(*) AS trials,
       count(*) FILTER (WHERE t.status = 'superseded') AS converted,
       round(100.0 * count(*) FILTER (WHERE t.status = 'superseded') / count(*), 1) AS conversion_pct
FROM subscriptions t
JOIN accounts a ON a.account_id = t.account_id
WHERE t.is_trial AND t.status <> 'trialing' AND NOT a.is_test_account
GROUP BY 1
ORDER BY conversion_pct DESC;
Churn reasons
SELECT cancel_reason, count(*) AS churned_subscriptions
FROM subscriptions
WHERE status = 'cancelled' AND NOT is_trial
GROUP BY cancel_reason
ORDER BY 2 DESC;
Weekly active users (distinct users with a login)
SELECT date_trunc('week', e.occurred_at)::date AS week, count(DISTINCT e.user_id) AS active_users
FROM events e
JOIN accounts a ON a.account_id = e.account_id
WHERE e.event_name = 'login' AND NOT a.is_test_account
  AND e.occurred_at >= TIMESTAMP '2025-10-01'
GROUP BY 1
ORDER BY 1;

Data dictionary

plans

5 rows · primary key (plan_id)

Price list. Prices are list prices; what a customer actually pays is subscriptions.mrr.

ColumnTypeNull?KeyDescription
plan_idintegerno PKUnique plan number.
plan_nametextnouniquestarter, team_legacy (retired at the end of 2023), growth, business or enterprise.
plan_ranksmallintnouniqueOrder of plans from smallest (1) to largest (5). A move to a higher rank is an upgrade.
monthly_pricenumeric(12,2)noList price per month on monthly billing, SAR. Enterprise prices are negotiated.
annual_pricenumeric(12,2)noList price per year on annual billing (10 × monthly: two months free), SAR.
seat_limitintegeryesMaximum users included. NULL = unlimited (enterprise).
is_activebooleannoFALSE for plans no longer sold to new customers.

accounts

605 rows · primary key (account_id)

Customer companies (one row per signup). Includes five internal test accounts that must be excluded from business metrics.

ColumnTypeNull?KeyDescription
account_idintegerno PKUnique account number (ascending with signup time).
account_nametextnoCompany name (fictional). Not unique: two different companies can share a name.
industrytextnoIndustry the customer operates in.
company_sizetextnoEmployee-count band.
citytextnoHead-office city.
countrychar(2)noISO country code: SA, AE, KW, BH, QA or OM.
created_attimestampnoSignup time. Its month is the account's cohort.
acquisition_channeltextnoHow the account found us: organic, paid (ads), partner, referral or sales (outbound sales team).
is_test_accountbooleannoTRUE for Mizan's own internal test and demo accounts.

users

2,804 rows · primary key (user_id)

People who can log in to an account. A user row is created when someone is invited; the matching 'signup' event is when they accepted.

ColumnTypeNull?KeyDescription
user_idintegerno PKUnique user number.
account_idintegerno accounts.account_idThe account (company) the user belongs to.
full_nametextnoUser's name (fictional).
emailtextnouniqueLogin email (example.com domains).
roletextnoadmin, member or viewer. Viewers cannot create reports.
created_attimestampnoWhen the user record was created (the account signup for the first user, otherwise the invitation time).
deactivated_attimestampyesWhen an admin deactivated the user. NULL = still enabled (even if the account has churned).
last_seen_attimestampyesTime of the user's latest event. NULL = never used the product (e.g. never accepted the invite).

subscriptions

989 rows · primary key (subscription_id)

Subscription history: one row per continuous period on one plan and billing cycle. Plan changes close the old row ('superseded') and open a new row the same day; trials are rows with is_trial = TRUE.

ColumnTypeNull?KeyDescription
subscription_idintegerno PKUnique subscription row number.
account_idintegerno accounts.account_idThe customer account.
plan_idintegerno plans.plan_idThe plan for this period.
is_trialbooleannoTRUE for the free 14-day trial (mrr = 0, never invoiced).
billing_cycletextnomonthly or annual billing.
seatsintegernoSeats purchased.
mrrnumeric(12,2)noMonthly recurring revenue of this row in SAR, after discounts (annual contracts: yearly value / 12).
started_atdatenoFirst day of this row.
ended_atdateyesDay the row stopped (exclusive: not active on this day). NULL = still running on 2025-12-31.
statustextnotrialing, active, past_due (running but unpaid), cancelled (customer left or trial expired) or superseded (replaced by a plan change or trial conversion).
cancel_reasontextyesWhy a cancelled row ended (e.g. too_expensive, low_usage, trial_expired). NULL for all other statuses.

invoices

2,885 rows · primary key (invoice_id)

Invoices issued for paid subscription rows: monthly plans are invoiced every month, annual plans once a year for 12 × mrr. Trials are never invoiced.

ColumnTypeNull?KeyDescription
invoice_idintegerno PKUnique invoice number.
subscription_idintegerno subscriptions.subscription_idThe subscription row being billed.
issued_ondatenoDate the invoice was issued.
due_ondatenoPayment due date (issued_on + 14 days).
period_startdatenoFirst day of the service period billed.
period_enddatenoLast day of the service period billed (inclusive).
amountnumeric(12,2)noInvoice total in SAR (excluding VAT).
statustextnopaid, open (awaiting payment), void (cancelled and usually re-issued) or uncollectible (written off).
paid_ondateyesDate payment was received. NULL unless status = 'paid'.

events

58,595 rows · primary key (event_id)

Product analytics events, one row per tracked action. Contains a small number of exact duplicates caused by client retries.

ColumnTypeNull?KeyDescription
event_idbigintno PKUnique event number (ascending with time).
user_idintegerno users.user_idWho performed the action.
account_idintegerno accounts.account_idThe user's account (denormalised for convenience).
event_nametextnosignup (user activated), login, create_report, share_report, invite_user, export_data or integration_connected.
occurred_attimestampnoWhen it happened (Riyadh local time).

support_tickets

1,205 rows · primary key (ticket_id)

Customer support tickets.

ColumnTypeNull?KeyDescription
ticket_idintegerno PKUnique ticket number.
account_idintegerno accounts.account_idThe customer account.
opened_by_user_idintegeryes users.user_idUser who opened the ticket. NULL when it came from an unknown email address.
opened_attimestampnoWhen the ticket was opened.
first_response_attimestampyesFirst reply from support. NULL = not answered yet.
closed_attimestampyesWhen the ticket was closed. NULL = still open on 2025-12-31.
prioritytextnolow, normal, high or urgent.
categorytextnohow_to, bug, billing, integration, account_access or feature_request.
satisfaction_scoresmallintyesCustomer rating 1–5 after closing. NULL = no survey answer.