Queries · q002 · Chief Executive Officer · week 1, night 1
“Has Tidewick's revenue become more or less concentrated among its largest merchants over the last two years?”
Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told
The manager, at the start of week 1
Subject: A few questions to get me oriented before the board meeting
Hi Hannah,
Thanks for taking these on this week — I know slots are tight, so please prioritize in the order below and don't force everything into this week if it doesn't fit cleanly. I'd rather get three solid answers than five rushed ones.
What I need this for: I'm building my mental model of the business ahead of the board meeting at the end of January, and I want my first real conversation with the board to show I understand where we're strong, where we're exposed, and what I'm watching closely. Your Friday memo will be the backbone of that.
Let me know if any of these need narrowing once you've had a look at what's feasible — happy to discuss before you lock in the report requests.
Thanks, Maren
The analyst · week 1, night 1, request 2 of 3
Maren's priority #1 is revenue concentration (which merchants/verticals drive volume and fees, and how that's shifted). I'm starting there with three complementary views at different grains, all built on payouts (gross/fee/net) since that's the cleanest, consistently-defined measure of money actually settled to/kept from merchants (the platform-plan billing of merchants isn't separately modeled in the warehouse as far as I can tell — I'll sanity-check that assumption before committing more slots to it). Report 1 gives merchant-level concentration today; Report 2 shows how that concentration has moved over the last 2 years; Report 3 rolls the same money up by vertical. Together these should let me describe dependency risk and set up next week's growth and fee-mix questions. Saving growth/fee-mix/vertical-health/risk questions for later nights per Maren's note that it's fine not to force everything into week one.
The engineer · 1 dry run on the empty schema, then the submission
WITH payout_fees_eur AS ( SELECT p.tenant_id, p.paid_at, p.fee_amount, p.currency_code, er.rate, p.fee_amount / er.rate AS fee_amount_eur FROM payouts p JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = p.currency_code AND er.as_of = CAST(p.paid_at AS date) WHERE p.paid_at IS NOT NULL AND p.paid_at >= DATE '2024-01-01' AND p.paid_at < DATE '2026-01-01' ), quarterly AS ( SELECT cd.year_num, cd.quarter_num, cd.year_num || '-Q' || cd.quarter_num AS quarter_label, pf.tenant_id, SUM(pf.fee_amount_eur) AS fee_eur FROM payout_fees_eur pf JOIN calendar_days cd ON cd.calendar_date = CAST(pf.paid_at AS date) GROUP BY 1, 2, 3, 4 ), ranked AS ( SELECT quarterly.*, ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC, tenant_id) AS rnk FROM quarterly ), quarter_totals AS ( SELECT quarter_label, year_num, quarter_num, COUNT(DISTINCT tenant_id) AS active_merchants, SUM(fee_eur) AS total_fee_eur FROM quarterly GROUP BY 1, 2, 3 ), top_sums AS ( SELECT quarter_label, SUM(fee_eur) FILTER (WHERE rnk <= 5) AS top5_fee_eur, SUM(fee_eur) FILTER (WHERE rnk <= 10) AS top10_fee_eur FROM ranked GROUP BY 1 ) SELECT qt.quarter_label AS quarter, qt.active_merchants, ROUND(qt.total_fee_eur, 2) AS total_fee_revenue_eur, ROUND(ts.top5_fee_eur, 2) AS top5_fee_revenue_eur, ROUND(100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top5_share_pct, ROUND(ts.top10_fee_eur, 2) AS top10_fee_revenue_eur, ROUND(100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top10_share_pct FROM quarter_totals qt JOIN top_sums ts ON ts.quarter_label = qt.quarter_label ORDER BY qt.year_num, qt.quarter_num
“Query compiles cleanly and returns exactly the 7 requested columns at one-row-per-quarter grain. Submitting.”
“Submitted. The report computes, for each of the 8 quarters (2024-Q1 through 2025-Q4): distinct active merchants with settled payouts, total EUR fee revenue, top-5 and top-10 merchant fee revenue and their shares of the quarter total — ranked by each tenant's quarterly fee revenue after EUR conversion via exchange_rates (EUR base, payout currency quote, rate as of paid_at date).”
As Hannah Brooks saw it, from the small dataset the agents worked on
quarter | active_merchants | total_fee_revenue_eur | top5_fee_revenue_eur | top5_share_pct | top10_fee_revenue_eur | top10_share_pct --------+------------------+-----------------------+----------------------+----------------+-----------------------+---------------- 2024-Q1 | 41 | 9224.35 | 7376.14 | 80.0 | 8325.44 | 90.3 2024-Q2 | 40 | 9506.65 | 7062.46 | 74.3 | 8360.34 | 87.9 2024-Q3 | 44 | 8562.88 | 6064.75 | 70.8 | 7289.39 | 85.1 2024-Q4 | 47 | 15633.97 | 11734.94 | 75.1 | 13312.84 | 85.2 2025-Q1 | 47 | 11429.2 | 7646.48 | 66.9 | 9485.42 | 83.0 2025-Q2 | 49 | 11612.46 | 8416.79 | 72.5 | 10001.83 | 86.1 2025-Q3 | 52 | 11047.02 | 8002.07 | 72.4 | 9260.04 | 83.8 2025-Q4 | 55 | 19097.17 | 14476.7 | 75.8 | 16429.07 | 86.0 (8 rows)
The memo and the queries that followed; links found by title, so inferred
Hannah Brooks's memo to Maren Okafor at the end of the week:
Trailing 12 months (TTM), Cragsley Outfitters alone drives 41.9% of fee revenue (€22.3k of €53.2k), and the top 5 merchants drive 72% (Merchant revenue concentration). At the vertical level, Apparel & Footwear is 54.6% of all fee revenue from just 12 merchants (Revenue by vertical, corrected). Concentration has been fairly stable over 8 quarters — top-5 share has ranged 67–80% with no clear trend (Revenue concentration trend by quarter). Confidence: high — the merchant and vertical totals now reconcile to the same €53,186 figure after I caught and fixed a vertical-report bug mid-week.
It builds on:
Changed only where the benchmark needs the same result on every system
WITH payout_fees_eur AS ( SELECT p.tenant_id, p.paid_at, p.fee_amount, p.currency_code, er.rate, p.fee_amount / er.rate AS fee_amount_eur p.tenant_id AS tenant_id, p.paid_at AS paid_at, p.fee_amount AS fee_amount, p.currency_code AS currency_code, er.rate AS rate, CAST(p.fee_amount / er.rate AS NUMERIC(18,6)) AS fee_amount_eur FROM payouts p JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = p.currency_code AND er.as_of = CAST(p.paid_at AS date) WHERE p.paid_at IS NOT NULL AND p.paid_at >= DATE '2024-01-01' AND p.paid_at < DATE '2026-01-01'),quarterly AS ( SELECT cd.year_num, cd.quarter_num, cd.year_num AS year_num, cd.quarter_num AS quarter_num, cd.year_num || '-Q' || cd.quarter_num AS quarter_label, pf.tenant_id, pf.tenant_id AS tenant_id, SUM(pf.fee_amount_eur) AS fee_eur FROM payout_fees_eur pf JOIN calendar_days cd ON cd.calendar_date = CAST(pf.paid_at AS date) GROUP BY 1, 2, 3, 4),ranked AS ( SELECT quarterly.*, ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC, tenant_id) AS rnk ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC NULLS FIRST, tenant_id NULLS LAST) AS rnk FROM quarterly),quarter_totals AS ( SELECT quarter_label, year_num, quarter_num, COUNT(DISTINCT tenant_id) AS active_merchants, SUM(fee_eur) AS total_fee_eur FROM quarterly GROUP BY 1, 2, 3),top_sums AS ( SELECT quarter_label, SUM(fee_eur) FILTER (WHERE rnk <= 5) AS top5_fee_eur, SUM(fee_eur) FILTER (WHERE rnk <= 10) AS top10_fee_eur FROM ranked GROUP BY 1)SELECT qt.quarter_label AS quarter, qt.active_merchants, ROUND(qt.total_fee_eur, 2) AS total_fee_revenue_eur, ROUND(ts.top5_fee_eur, 2) AS top5_fee_revenue_eur, ROUND(100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top5_share_pct, ROUND(ts.top10_fee_eur, 2) AS top10_fee_revenue_eur, ROUND(100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top10_share_pct qt.active_merchants AS active_merchants, qt.total_fee_eur AS total_fee_revenue_eur, ts.top5_fee_eur AS top5_fee_revenue_eur, 100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0) AS top5_share_pct, ts.top10_fee_eur AS top10_fee_revenue_eur, 100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0) AS top10_share_pctFROM quarter_totals qtJOIN top_sums ts ON ts.quarter_label = qt.quarter_labelORDER BY qt.year_num, qt.quarter_numORDER BY qt.year_num NULLS LAST, qt.quarter_num NULLS LAST
WITH payout_fees_eur AS ( SELECT p.tenant_id AS tenant_id, p.paid_at AS paid_at, p.fee_amount AS fee_amount, p.currency_code AS currency_code, er.rate AS rate, CAST(p.fee_amount / er.rate AS NUMERIC(18,6)) AS fee_amount_eur FROM payouts p JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = p.currency_code AND er.as_of = CAST(p.paid_at AS date) WHERE p.paid_at IS NOT NULL AND p.paid_at >= DATE '2024-01-01' AND p.paid_at < DATE '2026-01-01' ), quarterly AS ( SELECT cd.year_num AS year_num, cd.quarter_num AS quarter_num, cd.year_num || '-Q' || cd.quarter_num AS quarter_label, pf.tenant_id AS tenant_id, SUM(pf.fee_amount_eur) AS fee_eur FROM payout_fees_eur pf JOIN calendar_days cd ON cd.calendar_date = CAST(pf.paid_at AS date) GROUP BY 1, 2, 3, 4 ), ranked AS ( SELECT quarterly.*, ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC NULLS FIRST, tenant_id NULLS LAST) AS rnk FROM quarterly ), quarter_totals AS ( SELECT quarter_label, year_num, quarter_num, COUNT(DISTINCT tenant_id) AS active_merchants, SUM(fee_eur) AS total_fee_eur FROM quarterly GROUP BY 1, 2, 3 ), top_sums AS ( SELECT quarter_label, SUM(fee_eur) FILTER (WHERE rnk <= 5) AS top5_fee_eur, SUM(fee_eur) FILTER (WHERE rnk <= 10) AS top10_fee_eur FROM ranked GROUP BY 1 ) SELECT qt.quarter_label AS quarter, qt.active_merchants AS active_merchants, qt.total_fee_eur AS total_fee_revenue_eur, ts.top5_fee_eur AS top5_fee_revenue_eur, 100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0) AS top5_share_pct, ts.top10_fee_eur AS top10_fee_revenue_eur, 100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0) AS top10_share_pct FROM quarter_totals qt JOIN top_sums ts ON ts.quarter_label = qt.quarter_label ORDER BY qt.year_num NULLS LAST, qt.quarter_num NULLS LAST
The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted
Report request from Hannah Brooks (analyst for the Chief Executive Officer): Title: Revenue concentration trend by quarter Question: Has Tidewick's revenue become more or less concentrated among its largest merchants over the last two years? Grain: one row per calendar quarter Columns: - quarter (e.g. 2024-Q1) - active merchants with a payout that quarter - total fee revenue (EUR) - fee revenue from top 5 merchants that quarter (EUR) - top-5 share of fee revenue (%) - fee revenue from top 10 merchants that quarter (EUR) - top-10 share of fee revenue (%) Details: Source: payouts joined to tenants, same inclusion rule and EUR conversion method as the merchant-concentration report (convert via exchange_rates, base_code='EUR', quote_code=payout currency_code, as_of=payout paid_at date). Window: quarters from 2024-Q1 through 2025-Q4 (8 quarters), using calendar_days or payout paid_at to assign the quarter. For each quarter, rank merchants (tenant_id) by that quarter's fee revenue EUR and sum the top 5 and top 10 merchants' fee revenue to get top5/top10 shares of that quarter's total. 'Active merchants' = distinct tenant_id with qualifying payouts in that quarter. Order by quarter ascending. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runWITH payout_fees_eur AS ( SELECT p.tenant_id, p.paid_at, p.fee_amount, p.currency_code, er.rate, p.fee_amount / er.rate AS fee_amount_eur FROM payouts p JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = p.currency_code AND er.as_of = CAST(p.paid_at AS date) WHERE p.paid_at IS NOT NULL AND p.paid_at >= DATE '2024-01-01' AND p.paid_at < DATE '2026-01-01' ), quarterly AS ( SELECT cd.year_num, cd.quarter_num, cd.year_num || '-Q' || cd.quarter_num AS quarter_label, pf.tenant_id, SUM(pf.fee_amount_eur) AS fee_eur FROM payout_fees_eur pf JOIN calendar_days cd ON cd.calendar_date = CAST(pf.paid_at AS date) GROUP BY 1, 2, 3, 4 ), ranked AS ( SELECT quarterly.*, ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC, tenant_id) AS rnk FROM quarterly ), quarter_totals AS ( SELECT quarter_label, year_num, quarter_num, COUNT(DISTINCT tenant_id) AS active_merchants, SUM(fee_eur) AS total_fee_eur FROM quarterly GROUP BY 1, 2, 3 ), top_sums AS ( SELECT quarter_label, SUM(fee_eur) FILTER (WHERE rnk <= 5) AS top5_fee_eur, SUM(fee_eur) FILTER (WHERE rnk <= 10) AS top10_fee_eur FROM ranked GROUP BY 1 ) SELECT qt.quarter_label AS quarter, qt.active_merchants, ROUND(qt.total_fee_eur, 2) AS total_fee_revenue_eur, ROUND(ts.top5_fee_eur, 2) AS top5_fee_revenue_eur, ROUND(100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top5_share_pct, ROUND(ts.top10_fee_eur, 2) AS top10_fee_revenue_eur, ROUND(100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top10_share_pct FROM quarter_totals qt JOIN top_sums ts ON ts.quarter_label = qt.quarter_label ORDER BY qt.year_num, qt.quarter_num
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: quarter, active_merchants, total_fee_revenue_eur, top5_fee_revenue_eur, top5_share_pct, top10_fee_revenue_eur, top10_share_pct
submitWITH payout_fees_eur AS ( SELECT p.tenant_id, p.paid_at, p.fee_amount, p.currency_code, er.rate, p.fee_amount / er.rate AS fee_amount_eur FROM payouts p JOIN exchange_rates er ON er.base_code = 'EUR' AND er.quote_code = p.currency_code AND er.as_of = CAST(p.paid_at AS date) WHERE p.paid_at IS NOT NULL AND p.paid_at >= DATE '2024-01-01' AND p.paid_at < DATE '2026-01-01' ), quarterly AS ( SELECT cd.year_num, cd.quarter_num, cd.year_num || '-Q' || cd.quarter_num AS quarter_label, pf.tenant_id, SUM(pf.fee_amount_eur) AS fee_eur FROM payout_fees_eur pf JOIN calendar_days cd ON cd.calendar_date = CAST(pf.paid_at AS date) GROUP BY 1, 2, 3, 4 ), ranked AS ( SELECT quarterly.*, ROW_NUMBER() OVER (PARTITION BY quarter_label ORDER BY fee_eur DESC, tenant_id) AS rnk FROM quarterly ), quarter_totals AS ( SELECT quarter_label, year_num, quarter_num, COUNT(DISTINCT tenant_id) AS active_merchants, SUM(fee_eur) AS total_fee_eur FROM quarterly GROUP BY 1, 2, 3 ), top_sums AS ( SELECT quarter_label, SUM(fee_eur) FILTER (WHERE rnk <= 5) AS top5_fee_eur, SUM(fee_eur) FILTER (WHERE rnk <= 10) AS top10_fee_eur FROM ranked GROUP BY 1 ) SELECT qt.quarter_label AS quarter, qt.active_merchants, ROUND(qt.total_fee_eur, 2) AS total_fee_revenue_eur, ROUND(ts.top5_fee_eur, 2) AS top5_fee_revenue_eur, ROUND(100.0 * ts.top5_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top5_share_pct, ROUND(ts.top10_fee_eur, 2) AS top10_fee_revenue_eur, ROUND(100.0 * ts.top10_fee_eur / NULLIF(qt.total_fee_eur, 0), 1) AS top10_share_pct FROM quarter_totals qt JOIN top_sums ts ON ts.quarter_label = qt.quarter_label ORDER BY qt.year_num, qt.quarter_num
Submitted to tonight's batch. Your work on this request is done.