Queries · q003 · Chief Executive Officer · week 1, night 1
“Which merchant verticals (industries) generate the bulk of Tidewick's processing volume and fee revenue today?”
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 3 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 tenant_vertical AS ( SELECT t0.id AS tenant_id, COALESCE(NULLIF(TRIM(t0.industry), ''), 'Unspecified') AS vertical FROM tenants t0 ), fx AS ( SELECT er0.quote_code AS quote_code, er0.as_of AS as_of, er0.rate AS rate FROM exchange_rates er0 WHERE er0.base_code = 'EUR' ), qualifying_payouts AS ( SELECT p0.id AS payout_id, p0.tenant_id AS tenant_id, p0.currency_code AS currency_code, p0.gross_amount AS gross_amount, p0.fee_amount AS fee_amount, p0.paid_at AS paid_at, COALESCE(fx0.rate, 1.0) AS eur_rate FROM payouts p0 LEFT JOIN fx fx0 ON fx0.quote_code = p0.currency_code AND fx0.as_of = CAST(p0.paid_at AS date) WHERE p0.status = 'paid' AND p0.paid_at >= DATE '2025-01-01' AND p0.paid_at < DATE '2026-01-01' ), verticals AS ( SELECT DISTINCT tv0.vertical AS vertical FROM tenant_vertical tv0 JOIN qualifying_payouts qp0 ON qp0.tenant_id = tv0.tenant_id ), merchant_counts AS ( SELECT tv0.vertical AS vertical, COUNT(DISTINCT qp0.tenant_id) AS merchant_count FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), gross_volume AS ( SELECT tv0.vertical AS vertical, SUM(qp0.gross_amount / qp0.eur_rate) AS gross_volume_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), fee_revenue AS ( SELECT tv0.vertical AS vertical, SUM(qp0.fee_amount / qp0.eur_rate) AS fee_revenue_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), total_fee AS ( SELECT SUM(fr0.fee_revenue_eur) AS total_fee_revenue_eur FROM fee_revenue fr0 ) SELECT v0.vertical AS vertical, COALESCE(mc0.merchant_count, 0) AS merchant_count, ROUND(COALESCE(gv0.gross_volume_eur, 0), 2) AS gross_payment_volume_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0), 2) AS fee_revenue_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0), 2) AS avg_fee_revenue_per_merchant_eur, ROUND(100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0), 2) AS pct_of_total_fee_revenue FROM verticals v0 LEFT JOIN merchant_counts mc0 ON mc0.vertical = v0.vertical LEFT JOIN gross_volume gv0 ON gv0.vertical = v0.vertical LEFT JOIN fee_revenue fr0 ON fr0.vertical = v0.vertical CROSS JOIN total_fee t0 ORDER BY fee_revenue_eur DESC, vertical ASC
“Query compiles cleanly with the expected columns. Submitting.”
“Submitted. Summary of what the report does:
- Grain: one row per merchant vertical (tenants.industry), with nulls/blanks bucketed into 'Unspecified'.
- Window: payouts with paid_at in 2025-01-01 through 2025-12-31.
- Inclusion rule: status = 'paid' — this was my best-effort interpretation of "completed/settled," since the catalog doesn't list an enum for payouts.status. I flagged this in the submit note so it can be reconciled with the other two reports in the batch if they use a different code.
- Conversion: gross and fee amounts converted to EUR via exchange_rates (base_code = EUR) matched on currency and the payout's date, with EUR-currency payouts treated as rate 1.0.
- Columns: vertical, merchant count, gross payment volume (EUR), fee revenue (EUR), average fee revenue per merchant (EUR), share of total fee revenue (%) — 6 columns, well within the width limit.
- Ordering: fee revenue descending, tie-broken by vertical name ascending.”
As Hannah Brooks saw it, from the small dataset the agents worked on
vertical | merchant_count | gross_payment_volume_eur | fee_revenue_eur | avg_fee_revenue_per_merchant_eur | pct_of_total_fee_revenue --------------------------+----------------+--------------------------+-----------------+----------------------------------+------------------------- Apparel & Footwear | 22 | 1271676.54 | 32881.2 | 1494.6 | 35.14 Industrial Supplies (B2B) | 5 | 529299.94 | 12722.73 | 2544.55 | 13.6 Consumer Electronics | 8 | 576268.07 | 10116.22 | 1264.53 | 10.81 Food & Coffee | 11 | 317109.32 | 9692.1 | 881.1 | 10.36 Sports & Outdoor | 13 | 366001.45 | 9262.09 | 712.47 | 9.9 Office Supplies (B2B) | 4 | 435677.49 | 8633.49 | 2158.37 | 9.23 Home & Living | 16 | 238114.65 | 5173.66 | 323.35 | 5.53 Beauty | 14 | 152224.28 | 2887.84 | 206.27 | 3.09 Pet Supplies | 10 | 68004.17 | 1771.11 | 177.11 | 1.89 Jewelry & Accessories | 4 | 10530.25 | 250.26 | 62.57 | 0.27 Books & Stationery | 6 | 8081.84 | 192.51 | 32.08 | 0.21 (11 rows)
The memo and the queries that followed; links found by title, so inferred
Later queries that build on this report:
It builds on:
Changed only where the benchmark needs the same result on every system
WITH tenant_vertical AS ( SELECT t0.id AS tenant_id, COALESCE(NULLIF(TRIM(t0.industry), ''), 'Unspecified') AS vertical FROM tenants t0),fx AS ( SELECT er0.quote_code AS quote_code, er0.as_of AS as_of, er0.rate AS rate FROM exchange_rates er0 WHERE er0.base_code = 'EUR'),qualifying_payouts AS ( SELECT p0.id AS payout_id, p0.tenant_id AS tenant_id, p0.currency_code AS currency_code, p0.gross_amount AS gross_amount, p0.fee_amount AS fee_amount, p0.paid_at AS paid_at, COALESCE(fx0.rate, 1.0) AS eur_rate FROM payouts p0 LEFT JOIN fx fx0 ON fx0.quote_code = p0.currency_code AND fx0.as_of = CAST(p0.paid_at AS date) WHERE p0.status = 'paid' AND p0.paid_at >= DATE '2025-01-01' AND p0.paid_at < DATE '2026-01-01'),verticals AS ( SELECT DISTINCT tv0.vertical AS vertical FROM tenant_vertical tv0 JOIN qualifying_payouts qp0 ON qp0.tenant_id = tv0.tenant_id),merchant_counts AS ( SELECT tv0.vertical AS vertical, COUNT(DISTINCT qp0.tenant_id) AS merchant_count FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical),gross_volume AS ( SELECT tv0.vertical AS vertical, SUM(qp0.gross_amount / qp0.eur_rate) AS gross_volume_eur SUM(CAST(qp0.gross_amount / qp0.eur_rate AS NUMERIC(18,6))) AS gross_volume_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical),fee_revenue AS ( SELECT tv0.vertical AS vertical, SUM(qp0.fee_amount / qp0.eur_rate) AS fee_revenue_eur SUM(CAST(qp0.fee_amount / qp0.eur_rate AS NUMERIC(18,6))) AS fee_revenue_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical),total_fee AS ( SELECT SUM(fr0.fee_revenue_eur) AS total_fee_revenue_eur FROM fee_revenue fr0)SELECT v0.vertical AS vertical, COALESCE(mc0.merchant_count, 0) AS merchant_count, ROUND(COALESCE(gv0.gross_volume_eur, 0), 2) AS gross_payment_volume_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0), 2) AS fee_revenue_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0), 2) AS avg_fee_revenue_per_merchant_eur, ROUND(100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0), 2) AS pct_of_total_fee_revenue COALESCE(gv0.gross_volume_eur, 0) AS gross_payment_volume_eur, COALESCE(fr0.fee_revenue_eur, 0) AS fee_revenue_eur, COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0) AS avg_fee_revenue_per_merchant_eur, 100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0) AS pct_of_total_fee_revenueFROM verticals v0LEFT JOIN merchant_counts mc0 ON mc0.vertical = v0.verticalLEFT JOIN gross_volume gv0 ON gv0.vertical = v0.verticalLEFT JOIN fee_revenue fr0 ON fr0.vertical = v0.verticalCROSS JOIN total_fee t0ORDER BY fee_revenue_eur DESC, vertical ASCORDER BY fee_revenue_eur DESC NULLS FIRST, vertical ASC NULLS LAST
WITH tenant_vertical AS ( SELECT t0.id AS tenant_id, COALESCE(NULLIF(TRIM(t0.industry), ''), 'Unspecified') AS vertical FROM tenants t0 ), fx AS ( SELECT er0.quote_code AS quote_code, er0.as_of AS as_of, er0.rate AS rate FROM exchange_rates er0 WHERE er0.base_code = 'EUR' ), qualifying_payouts AS ( SELECT p0.id AS payout_id, p0.tenant_id AS tenant_id, p0.currency_code AS currency_code, p0.gross_amount AS gross_amount, p0.fee_amount AS fee_amount, p0.paid_at AS paid_at, COALESCE(fx0.rate, 1.0) AS eur_rate FROM payouts p0 LEFT JOIN fx fx0 ON fx0.quote_code = p0.currency_code AND fx0.as_of = CAST(p0.paid_at AS date) WHERE p0.status = 'paid' AND p0.paid_at >= DATE '2025-01-01' AND p0.paid_at < DATE '2026-01-01' ), verticals AS ( SELECT DISTINCT tv0.vertical AS vertical FROM tenant_vertical tv0 JOIN qualifying_payouts qp0 ON qp0.tenant_id = tv0.tenant_id ), merchant_counts AS ( SELECT tv0.vertical AS vertical, COUNT(DISTINCT qp0.tenant_id) AS merchant_count FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), gross_volume AS ( SELECT tv0.vertical AS vertical, SUM(CAST(qp0.gross_amount / qp0.eur_rate AS NUMERIC(18,6))) AS gross_volume_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), fee_revenue AS ( SELECT tv0.vertical AS vertical, SUM(CAST(qp0.fee_amount / qp0.eur_rate AS NUMERIC(18,6))) AS fee_revenue_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), total_fee AS ( SELECT SUM(fr0.fee_revenue_eur) AS total_fee_revenue_eur FROM fee_revenue fr0 ) SELECT v0.vertical AS vertical, COALESCE(mc0.merchant_count, 0) AS merchant_count, COALESCE(gv0.gross_volume_eur, 0) AS gross_payment_volume_eur, COALESCE(fr0.fee_revenue_eur, 0) AS fee_revenue_eur, COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0) AS avg_fee_revenue_per_merchant_eur, 100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0) AS pct_of_total_fee_revenue FROM verticals v0 LEFT JOIN merchant_counts mc0 ON mc0.vertical = v0.vertical LEFT JOIN gross_volume gv0 ON gv0.vertical = v0.vertical LEFT JOIN fee_revenue fr0 ON fr0.vertical = v0.vertical CROSS JOIN total_fee t0 ORDER BY fee_revenue_eur DESC NULLS FIRST, vertical ASC 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 by vertical, trailing 12 months Question: Which merchant verticals (industries) generate the bulk of Tidewick's processing volume and fee revenue today? Grain: one row per merchant vertical (tenants.industry) Columns: - vertical (industry) - merchant count (distinct tenants with a qualifying payout) - gross payment volume (EUR) - fee revenue (EUR) - average fee revenue per merchant (EUR) - share of total fee revenue (%) Details: Source: payouts joined to tenants on tenant_id for industry. Same window (paid_at 2025-01-01 to 2025-12-31), same inclusion rule (completed/settled payouts only), and same EUR conversion method via exchange_rates as the other two reports in this batch. Group by tenants.industry. Order by fee revenue EUR descending, tie-break by vertical name ascending. If industry is null/blank for some tenants, group those into a single 'Unspecified' row rather than dropping them. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runWITH tenant_vertical AS ( SELECT t0.id AS tenant_id, COALESCE(NULLIF(TRIM(t0.industry), ''), 'Unspecified') AS vertical FROM tenants t0 ), fx AS ( SELECT er0.quote_code AS quote_code, er0.as_of AS as_of, er0.rate AS rate FROM exchange_rates er0 WHERE er0.base_code = 'EUR' ), qualifying_payouts AS ( SELECT p0.id AS payout_id, p0.tenant_id AS tenant_id, p0.currency_code AS currency_code, p0.gross_amount AS gross_amount, p0.fee_amount AS fee_amount, p0.paid_at AS paid_at, COALESCE(fx0.rate, 1.0) AS eur_rate FROM payouts p0 LEFT JOIN fx fx0 ON fx0.quote_code = p0.currency_code AND fx0.as_of = CAST(p0.paid_at AS date) WHERE p0.status = 'paid' AND p0.paid_at >= DATE '2025-01-01' AND p0.paid_at < DATE '2026-01-01' ), verticals AS ( SELECT DISTINCT tv0.vertical AS vertical FROM tenant_vertical tv0 JOIN qualifying_payouts qp0 ON qp0.tenant_id = tv0.tenant_id ), merchant_counts AS ( SELECT tv0.vertical AS vertical, COUNT(DISTINCT qp0.tenant_id) AS merchant_count FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), gross_volume AS ( SELECT tv0.vertical AS vertical, SUM(qp0.gross_amount / qp0.eur_rate) AS gross_volume_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), fee_revenue AS ( SELECT tv0.vertical AS vertical, SUM(qp0.fee_amount / qp0.eur_rate) AS fee_revenue_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), total_fee AS ( SELECT SUM(fr0.fee_revenue_eur) AS total_fee_revenue_eur FROM fee_revenue fr0 ) SELECT v0.vertical AS vertical, COALESCE(mc0.merchant_count, 0) AS merchant_count, ROUND(COALESCE(gv0.gross_volume_eur, 0), 2) AS gross_payment_volume_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0), 2) AS fee_revenue_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0), 2) AS avg_fee_revenue_per_merchant_eur, ROUND(100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0), 2) AS pct_of_total_fee_revenue FROM verticals v0 LEFT JOIN merchant_counts mc0 ON mc0.vertical = v0.vertical LEFT JOIN gross_volume gv0 ON gv0.vertical = v0.vertical LEFT JOIN fee_revenue fr0 ON fr0.vertical = v0.vertical CROSS JOIN total_fee t0 ORDER BY fee_revenue_eur DESC, vertical ASC
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: vertical, merchant_count, gross_payment_volume_eur, fee_revenue_eur, avg_fee_revenue_per_merchant_eur, pct_of_total_fee_revenue
submitWITH tenant_vertical AS ( SELECT t0.id AS tenant_id, COALESCE(NULLIF(TRIM(t0.industry), ''), 'Unspecified') AS vertical FROM tenants t0 ), fx AS ( SELECT er0.quote_code AS quote_code, er0.as_of AS as_of, er0.rate AS rate FROM exchange_rates er0 WHERE er0.base_code = 'EUR' ), qualifying_payouts AS ( SELECT p0.id AS payout_id, p0.tenant_id AS tenant_id, p0.currency_code AS currency_code, p0.gross_amount AS gross_amount, p0.fee_amount AS fee_amount, p0.paid_at AS paid_at, COALESCE(fx0.rate, 1.0) AS eur_rate FROM payouts p0 LEFT JOIN fx fx0 ON fx0.quote_code = p0.currency_code AND fx0.as_of = CAST(p0.paid_at AS date) WHERE p0.status = 'paid' AND p0.paid_at >= DATE '2025-01-01' AND p0.paid_at < DATE '2026-01-01' ), verticals AS ( SELECT DISTINCT tv0.vertical AS vertical FROM tenant_vertical tv0 JOIN qualifying_payouts qp0 ON qp0.tenant_id = tv0.tenant_id ), merchant_counts AS ( SELECT tv0.vertical AS vertical, COUNT(DISTINCT qp0.tenant_id) AS merchant_count FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), gross_volume AS ( SELECT tv0.vertical AS vertical, SUM(qp0.gross_amount / qp0.eur_rate) AS gross_volume_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), fee_revenue AS ( SELECT tv0.vertical AS vertical, SUM(qp0.fee_amount / qp0.eur_rate) AS fee_revenue_eur FROM qualifying_payouts qp0 JOIN tenant_vertical tv0 ON tv0.tenant_id = qp0.tenant_id GROUP BY tv0.vertical ), total_fee AS ( SELECT SUM(fr0.fee_revenue_eur) AS total_fee_revenue_eur FROM fee_revenue fr0 ) SELECT v0.vertical AS vertical, COALESCE(mc0.merchant_count, 0) AS merchant_count, ROUND(COALESCE(gv0.gross_volume_eur, 0), 2) AS gross_payment_volume_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0), 2) AS fee_revenue_eur, ROUND(COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(COALESCE(mc0.merchant_count, 0), 0), 2) AS avg_fee_revenue_per_merchant_eur, ROUND(100.0 * COALESCE(fr0.fee_revenue_eur, 0) / NULLIF(t0.total_fee_revenue_eur, 0), 2) AS pct_of_total_fee_revenue FROM verticals v0 LEFT JOIN merchant_counts mc0 ON mc0.vertical = v0.vertical LEFT JOIN gross_volume gv0 ON gv0.vertical = v0.vertical LEFT JOIN fee_revenue fr0 ON fr0.vertical = v0.vertical CROSS JOIN total_fee t0 ORDER BY fee_revenue_eur DESC, vertical ASC
Submitted to tonight's batch. Your work on this request is done.