DB Olympics

Queries · q261 · Head of Growth Marketing · week 2, night 2

Referral reach and value by vertical

“Which verticals already have the most referral-driven customers relative to their size, and does the referrer revenue advantage seen platform-wide hold within each vertical too?”

Manager · asked the questionChloé MarchettiHead of Growth Marketing. Joined from a direct-to-consumer brand. Wants to sell merchants more of Tidewick's marketing tools.
Analyst · planned the reportSofie NilsenStoryteller: looks for the two or three findings that matter and digs until each is explained.
Engineer · wrote the SQLInesThinks in window functions: ranks, running totals, LAG/LEAD for comparisons, percent-of-total.

Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told

  1. Chloé Marchetti writes to Sofie Nilsen

    The manager, at the start of week 2

    Subject: Good progress — four things I want nailed down this week

    Hi Sofie,

    Thanks for this — genuinely useful, and the vertical breakdown on discounting is exactly the kind of "don't trust the pooled number" catch I was worried about. A few things surprised me and I want to go deeper before I take anything to leadership.

    What surprised me / needs explaining:

    • Aisha's team flagged that loyalty members "cost" nearly a fifth of their own revenue in redeemed points, plus a large pile of points issued but not yet redeemed sitting as a liability. That's a very different lens from AOV — a program can look flat on AOV and still be expensive. I want these two views reconciled, not treated as separate facts.
    • Aisha also walked back the "loyalty members return more" claim once category mix was accounted for. That's a good catch, but it makes me nervous about the apparel-vs-electronics AOV comparison in your memo — is that difference also just a category mix artifact, or is it real?
    • Referrals look like our best-performing lever by far, yet reach is under 1% of customers. That gap between "strong where it exists" and "barely exists" feels like the single biggest opportunity I've seen all week.

    My questions for this week, roughly in priority order:

    1. Does discounting actually cost us margin, and in which verticals is it worst? This was already your next step — please keep it top of the list. I need a real cost picture (not just return rates) before I tell merchants to rein in sitewide sales.
    2. Is the loyalty programme actually worth running as-is? I want one clear picture that weighs what members cost us (redeemed and owed points) against what they're worth (spend, frequency, retention), controlling for the category mix issue Aisha found. I need to decide whether we fix it, shrink it, or let it be.
    3. What would it take to grow referrals, and who's a good referrer? Given how strong but tiny this program is, I want to understand what referring customers look like (so we can find more of them) and whether growth here looks more promising than fixing loyalty.
    4. Of the orders we can't currently link to a channel, is there any pattern at all (timing, merchant type, repeat vs new customer) that hints at what's driving them? I don't expect a clean answer — I just want to know if this blind spot is worth investing in closing, or if it's simply untrackable and I should stop asking.

    What I need this for: I'm trying to turn this into a short list of 2-3 concrete recommendations for merchants and for our own roadmap — where to tell them to pull back (discounting), where to double down (referrals), and where we might be quietly burning money (loyalty payouts). I'd rather have fewer, firmer answers than a wider, shakier set.

    Thanks again — this is coming together well.

    Chloé

  2. Sofie Nilsen plans the night

    The analyst · week 2, night 2, request 3 of 3

    Night 1 settled Q1: discounting's real cost is heavily vertical-dependent. Apparel, Beauty, Home & Living, and Sports & Outdoor show discounted orders costing 17-42 percentage points more of GMV (combined discount+refund) than full-price orders in the same vertical — genuine margin leakage worth telling merchants to rein in. Food & Coffee and Pet Supplies show even bigger leakage % (83-89%), but that's near-free subscription trial offers, a different (acquisition-cost) story, not wasteful promo. The coupon-code report found only 5 distinct code templates drive almost all 2025 redemptions platform-wide, with WELCOME10 alone responsible for €51k net cost (discount+refund) — confirms and quantifies Oliver's finding, and the monthly trend confirms leakage worsened into Q3/Q4, tracking the refund-rate creep CEO/CFO flagged. Q1 is in good shape for the memo. Tonight I'm moving to Q2 (loyalty): Ingrid's team already gave the company-wide cost number (19.4% of member revenue redeemed, €669k outstanding liability) and the category-mix correction on returns, so I'm pushing that down to the vertical level (cost) and adding the one 'worth' metric Chloé asked for that we're missing — retention/repeat-purchase rate, controlled by category. Third slot starts Q3 (referrals) at the same vertical grain for comparability, to see where reach is least tapped.

    Referral reach and value by vertical
    Question
    Which verticals already have the most referral-driven customers relative to their size, and does the referrer revenue advantage seen platform-wide hold within each vertical too?
    One row per
    industry and segment ('referrer' vs 'non-referrer')
    Columns
    • industry - tenants.industry
    • segment - 'referrer' (user_id appears in referrals.referrer_user_id) or 'non-referrer'
    • users_count - distinct users in that segment who placed >=1 order with placed_at in 2025 in this industry
    • share_of_industry_users_pct - users_count / total active 2025 shoppers in that industry * 100, rounded in 2 decimals
    • avg_orders_per_user - average count of 2025 orders per user in that segment, rounded to 2 decimals
    • avg_order_value_eur - average grand_total (EUR) of that segment's 2025 orders in this industry, rounded to 0 decimals
  3. Ines writes the SQL

    The engineer · 1 dry run on the empty schema, then the submission

    Dry run 1 · STATUS: COMPILES (dry run on the empty schema, no data read)
    WITH order_amounts AS (
      SELECT
        o.id AS order_id,
        o.tenant_id,
        o.user_id,
        o.grand_total / er.rate AS grand_total_eur
      FROM orders o
      JOIN exchange_rates er
        ON er.base_code = 'EUR'
        AND er.quote_code = o.currency_code
        AND er.as_of = CAST(o.placed_at AS date)
      WHERE o.placed_at >= DATE '2025-01-01'
        AND o.placed_at < DATE '2026-01-01'
    ),
    flagged AS (
      SELECT
        oa.order_id,
        oa.tenant_id,
        oa.user_id,
        oa.grand_total_eur,
        t.industry,
        CASE WHEN EXISTS (
          SELECT 1 FROM referrals r
          WHERE r.tenant_id = oa.tenant_id AND r.referrer_user_id = oa.user_id
        ) THEN 'referrer' ELSE 'non-referrer' END AS segment
      FROM order_amounts oa
      JOIN tenants t ON t.id = oa.tenant_id
      WHERE t.industry IS NOT NULL
    ),
    user_level AS (
      SELECT industry, segment, tenant_id, user_id, COUNT(*) AS orders_count
      FROM flagged
      GROUP BY industry, segment, tenant_id, user_id
    ),
    industry_user_totals AS (
      SELECT industry, COUNT(*) AS total_users
      FROM (SELECT DISTINCT industry, tenant_id, user_id FROM flagged) x
      GROUP BY industry
    ),
    segment_agg AS (
      SELECT industry, segment,
        COUNT(*) AS users_count,
        AVG(orders_count) AS avg_orders_per_user
      FROM user_level
      GROUP BY industry, segment
    ),
    order_level_agg AS (
      SELECT industry, segment, AVG(grand_total_eur) AS avg_order_value_eur
      FROM flagged
      GROUP BY industry, segment
    )
    SELECT
      s.industry,
      s.segment,
      s.users_count,
      ROUND(100.0 * s.users_count / t.total_users, 2) AS share_of_industry_users_pct,
      ROUND(s.avg_orders_per_user, 2) AS avg_orders_per_user,
      ROUND(o.avg_order_value_eur, 0) AS avg_order_value_eur
    FROM segment_agg s
    JOIN industry_user_totals t ON t.industry = s.industry
    JOIN order_level_agg o ON o.industry = s.industry AND o.segment = s.segment
    ORDER BY s.industry ASC, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 END

    “Query compiles and returns the expected columns at the industry × segment grain. Submitting now.”

    Submitted · the SQL of the last dry run, unchanged · Submitted to tonight's batch. Your work on this request is done.

    “Submitted. Summary of what the report delivers: - Grain: one row per industry × segment (referrer / non-referrer). - users_count: distinct users per segment with ≥1 order placed in 2025 in that industry. - share_of_industry_users_pct: that segment's users as a % of all 2025 active shoppers in the industry. - avg_orders_per_user: mean 2025 order count per user in the segment. - avg_order_value_eur: mean per-order grand_total converted to EUR via exchange_rates (base EUR, rate as of the order's placed date), rounded to the nearest euro. Noted in the submission: segments are ordered referrer before non-referrer within each industry, "referrer" status is based on ever appearing as a referrals.referrer_user_id for that tenant (not redemption-dependent), and tenants with a null industry were dropped since they have no vertical to report against.”

  4. The report comes back overnight

    As Sofie Nilsen saw it, from the small dataset the agents worked on

    industry                  | segment      | users_count | share_of_industry_users_pct | avg_orders_per_user | avg_order_value_eur
    --------------------------+--------------+-------------+-----------------------------+---------------------+--------------------
    Apparel & Footwear        | referrer     |         104 |                        4.58 |                4.02 |               179.0
    Apparel & Footwear        | non-referrer |        2168 |                       95.42 |                2.55 |               187.0
    Beauty                    | referrer     |          25 |                        6.04 |                4.68 |                84.0
    Beauty                    | non-referrer |         389 |                       93.96 |                2.99 |               100.0
    Books & Stationery        | referrer     |           4 |                        9.76 |                4.25 |                55.0
    Books & Stationery        | non-referrer |          37 |                       90.24 |                2.76 |                47.0
    Consumer Electronics      | non-referrer |          20 |                       100.0 |                2.35 |               796.0
    Food & Coffee             | referrer     |          24 |                       12.12 |               13.67 |                19.0
    Food & Coffee             | non-referrer |         174 |                       87.88 |                8.37 |                29.0
    Home & Living             | referrer     |          16 |                        4.13 |                4.94 |               187.0
    Home & Living             | non-referrer |         371 |                       95.87 |                2.06 |               156.0
    Industrial Supplies (B2B) | referrer     |           5 |                       14.29 |                 7.4 |              2136.0
    Industrial Supplies (B2B) | non-referrer |          30 |                       85.71 |                4.07 |              2530.0
    Jewelry & Accessories     | non-referrer |           9 |                       100.0 |                1.56 |               235.0
    Office Supplies (B2B)     | referrer     |           8 |                       16.67 |                7.13 |              1705.0
    Office Supplies (B2B)     | non-referrer |          40 |                       83.33 |                 4.7 |              3279.0
    Pet Supplies              | referrer     |          20 |                       10.87 |                 9.3 |                36.0
    Pet Supplies              | non-referrer |         164 |                       89.13 |                 5.7 |                41.0
    Sports & Outdoor          | referrer     |          13 |                        5.33 |                3.69 |               422.0
    Sports & Outdoor          | non-referrer |         231 |                       94.67 |                2.19 |               381.0
    (20 rows)
  5. What came of it

    The memo and the queries that followed; links found by title, so inferred

    Sofie Nilsen's memo to Chloé Marchetti at the end of the week:

    • 3. Referrals: still the best lever, and reachable earlier than I thought. Referrers order 1.5–2.4x more often than non-referrers in every single vertical (Report: Referral reach and value by vertical) — a robust, category-proof signal. On timing, 43% of referrers only refer after 6+ orders, but 41% refer within their first 1–3 orders — so this isn't purely a "wait for power users" dynamic; there's room to prompt earlier in the lifecycle. Reach is still under 17% even in the best vertical. Recommend: test an earlier referral prompt (after order 2–3) as the growth lever, ahead of fixing loyalty.

    Later queries that build on this report:

    It builds on:

  6. It becomes benchmark query q261

    Changed only where the benchmark needs the same result on every system

    • numericsdocs/NUMERICS.md: AVG over an integer computed as a decimal: AVG(CAST(x AS NUMERIC(18,6)))
    • numericsdocs/NUMERICS.md: rounding removed; results keep full precision
    • numericsdocs/NUMERICS.md: x / exchange rate cast to NUMERIC(18,6)
    • made explicita selected t.col gets AS col, its standard name made explicit (10×)
    • determinismthe standard leaves the place of NULLs in a sort to the implementation: NULLS LAST ascending, NULLS FIRST descending, as in the reference results (2×)
    The benchmark text, against the submitted SQL
    WITH order_amounts AS (  SELECT    o.id AS order_id,    o.tenant_id,    o.user_id,    o.grand_total / er.rate AS grand_total_eur    o.tenant_id AS tenant_id,    o.user_id AS user_id,    CAST(o.grand_total / er.rate AS NUMERIC(18,6)) AS grand_total_eur  FROM orders o  JOIN exchange_rates er    ON er.base_code = 'EUR'    AND er.quote_code = o.currency_code    AND er.as_of = CAST(o.placed_at AS date)  WHERE o.placed_at >= DATE '2025-01-01'    AND o.placed_at < DATE '2026-01-01'),flagged AS (  SELECT    oa.order_id,    oa.tenant_id,    oa.user_id,    oa.grand_total_eur,    t.industry,    oa.order_id AS order_id,    oa.tenant_id AS tenant_id,    oa.user_id AS user_id,    oa.grand_total_eur AS grand_total_eur,    t.industry AS industry,    CASE WHEN EXISTS (      SELECT 1 FROM referrals r      WHERE r.tenant_id = oa.tenant_id AND r.referrer_user_id = oa.user_id    ) THEN 'referrer' ELSE 'non-referrer' END AS segment  FROM order_amounts oa  JOIN tenants t ON t.id = oa.tenant_id  WHERE t.industry IS NOT NULL),user_level AS (  SELECT industry, segment, tenant_id, user_id, COUNT(*) AS orders_count  FROM flagged  GROUP BY industry, segment, tenant_id, user_id),industry_user_totals AS (  SELECT industry, COUNT(*) AS total_users  FROM (SELECT DISTINCT industry, tenant_id, user_id FROM flagged) x  GROUP BY industry),segment_agg AS (  SELECT industry, segment,    COUNT(*) AS users_count,    AVG(orders_count) AS avg_orders_per_user    AVG(CAST(orders_count AS NUMERIC(18,6))) AS avg_orders_per_user  FROM user_level  GROUP BY industry, segment),order_level_agg AS (  SELECT industry, segment, AVG(grand_total_eur) AS avg_order_value_eur  FROM flagged  GROUP BY industry, segment)SELECT  s.industry,  s.segment,  s.users_count,  ROUND(100.0 * s.users_count / t.total_users, 2) AS share_of_industry_users_pct,  ROUND(s.avg_orders_per_user, 2) AS avg_orders_per_user,  ROUND(o.avg_order_value_eur, 0) AS avg_order_value_eur  s.industry AS industry,  s.segment AS segment,  s.users_count AS users_count,  100.0 * s.users_count / t.total_users AS share_of_industry_users_pct,  s.avg_orders_per_user AS avg_orders_per_user,  o.avg_order_value_eur AS avg_order_value_eurFROM segment_agg sJOIN industry_user_totals t ON t.industry = s.industryJOIN order_level_agg o ON o.industry = s.industry AND o.segment = s.segmentORDER BY s.industry ASC, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 ENDORDER BY s.industry ASC NULLS LAST, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 END NULLS LAST
    WITH order_amounts AS (
      SELECT
        o.id AS order_id,
        o.tenant_id AS tenant_id,
        o.user_id AS user_id,
        CAST(o.grand_total / er.rate AS NUMERIC(18,6)) AS grand_total_eur
      FROM orders o
      JOIN exchange_rates er
        ON er.base_code = 'EUR'
        AND er.quote_code = o.currency_code
        AND er.as_of = CAST(o.placed_at AS date)
      WHERE o.placed_at >= DATE '2025-01-01'
        AND o.placed_at < DATE '2026-01-01'
    ),
    flagged AS (
      SELECT
        oa.order_id AS order_id,
        oa.tenant_id AS tenant_id,
        oa.user_id AS user_id,
        oa.grand_total_eur AS grand_total_eur,
        t.industry AS industry,
        CASE WHEN EXISTS (
          SELECT 1 FROM referrals r
          WHERE r.tenant_id = oa.tenant_id AND r.referrer_user_id = oa.user_id
        ) THEN 'referrer' ELSE 'non-referrer' END AS segment
      FROM order_amounts oa
      JOIN tenants t ON t.id = oa.tenant_id
      WHERE t.industry IS NOT NULL
    ),
    user_level AS (
      SELECT industry, segment, tenant_id, user_id, COUNT(*) AS orders_count
      FROM flagged
      GROUP BY industry, segment, tenant_id, user_id
    ),
    industry_user_totals AS (
      SELECT industry, COUNT(*) AS total_users
      FROM (SELECT DISTINCT industry, tenant_id, user_id FROM flagged) x
      GROUP BY industry
    ),
    segment_agg AS (
      SELECT industry, segment,
        COUNT(*) AS users_count,
        AVG(CAST(orders_count AS NUMERIC(18,6))) AS avg_orders_per_user
      FROM user_level
      GROUP BY industry, segment
    ),
    order_level_agg AS (
      SELECT industry, segment, AVG(grand_total_eur) AS avg_order_value_eur
      FROM flagged
      GROUP BY industry, segment
    )
    SELECT
      s.industry AS industry,
      s.segment AS segment,
      s.users_count AS users_count,
      100.0 * s.users_count / t.total_users AS share_of_industry_users_pct,
      s.avg_orders_per_user AS avg_orders_per_user,
      o.avg_order_value_eur AS avg_order_value_eur
    FROM segment_agg s
    JOIN industry_user_totals t ON t.industry = s.industry
    JOIN order_level_agg o ON o.industry = s.industry AND o.segment = s.segment
    ORDER BY s.industry ASC NULLS LAST, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 END NULLS LAST
    100 ms1 s10 sHyper2.46 sDuckDB233 msGizmoSQL231 msclickhouse_brew3.23 sFirebolterrorDataFusionerrorClickHouseerror
    • Firebolt{ "errors": [ { "description": "Line 6, Column 24: Operations between decimals with different precision and scale is not supported at the moment. Explicitly cast one of the decimals to other decimal precision and scale." } ], "query": { "query_id": "93198fe9-0c66-4fd3-9b17-2e663da7361f", "query_labe
    • DataFusionThis feature is not implemented: Physical plan does not support logical expression Exists(Exists { subquery: <subquery>, negated: false })
    • ClickHouseCode: 69. DB::Exception: Decimal result's scale is less than argument's one: while executing function divide on arguments __table27.grand_total Decimal(14, 4) Decimal64(size = 0), __table28.rate Decimal(12, 6) Decimal64(size = 0). (ARGUMENT_OUT_OF_BOUND)
  7. Everything, as recorded

    The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted

    Ines's whole session, 7 turns
    • The request, as Ines received it
      Report request from Sofie Nilsen (analyst for the Head of Growth Marketing):
      
      Title: Referral reach and value by vertical
      Question: Which verticals already have the most referral-driven customers relative to their size, and does the referrer revenue advantage seen platform-wide hold within each vertical too?
      Grain: one row per industry and segment ('referrer' vs 'non-referrer')
      Columns:
      - industry - tenants.industry
      - segment - 'referrer' (user_id appears in referrals.referrer_user_id) or 'non-referrer'
      - users_count - distinct users in that segment who placed >=1 order with placed_at in 2025 in this industry
      - share_of_industry_users_pct - users_count / total active 2025 shoppers in that industry * 100, rounded in 2 decimals
      - avg_orders_per_user - average count of 2025 orders per user in that segment, rounded to 2 decimals
      - avg_order_value_eur - average grand_total (EUR) of that segment's 2025 orders in this industry, rounded to 0 decimals
      Details: Source: orders joined to tenants (industry) and referrals (referrer match on user_id+tenant_id = referrer_user_id). Filter placed_at in 2025, all tenants (no restriction to loyalty-only tenants here, since referrals is a separate feature). Convert grand_total to EUR using exchange_rates as of placed_at date (EUR=rate 1). Order by industry ascending, then segment ascending ('non-referrer' then 'referrer', or vice versa — pick one consistent order and state it: 'referrer' before 'non-referrer'). Expect roughly 9-10 industries x 2 rows.
      
      Check your query with the warehouse's dry_run tool, then hand it in with submit.
    • Ines calls dry_run
      WITH order_amounts AS (
        SELECT
          o.id AS order_id,
          o.tenant_id,
          o.user_id,
          o.grand_total / er.rate AS grand_total_eur
        FROM orders o
        JOIN exchange_rates er
          ON er.base_code = 'EUR'
          AND er.quote_code = o.currency_code
          AND er.as_of = CAST(o.placed_at AS date)
        WHERE o.placed_at >= DATE '2025-01-01'
          AND o.placed_at < DATE '2026-01-01'
      ),
      flagged AS (
        SELECT
          oa.order_id,
          oa.tenant_id,
          oa.user_id,
          oa.grand_total_eur,
          t.industry,
          CASE WHEN EXISTS (
            SELECT 1 FROM referrals r
            WHERE r.tenant_id = oa.tenant_id AND r.referrer_user_id = oa.user_id
          ) THEN 'referrer' ELSE 'non-referrer' END AS segment
        FROM order_amounts oa
        JOIN tenants t ON t.id = oa.tenant_id
        WHERE t.industry IS NOT NULL
      ),
      user_level AS (
        SELECT industry, segment, tenant_id, user_id, COUNT(*) AS orders_count
        FROM flagged
        GROUP BY industry, segment, tenant_id, user_id
      ),
      industry_user_totals AS (
        SELECT industry, COUNT(*) AS total_users
        FROM (SELECT DISTINCT industry, tenant_id, user_id FROM flagged) x
        GROUP BY industry
      ),
      segment_agg AS (
        SELECT industry, segment,
          COUNT(*) AS users_count,
          AVG(orders_count) AS avg_orders_per_user
        FROM user_level
        GROUP BY industry, segment
      ),
      order_level_agg AS (
        SELECT industry, segment, AVG(grand_total_eur) AS avg_order_value_eur
        FROM flagged
        GROUP BY industry, segment
      )
      SELECT
        s.industry,
        s.segment,
        s.users_count,
        ROUND(100.0 * s.users_count / t.total_users, 2) AS share_of_industry_users_pct,
        ROUND(s.avg_orders_per_user, 2) AS avg_orders_per_user,
        ROUND(o.avg_order_value_eur, 0) AS avg_order_value_eur
      FROM segment_agg s
      JOIN industry_user_totals t ON t.industry = s.industry
      JOIN order_level_agg o ON o.industry = s.industry AND o.segment = s.segment
      ORDER BY s.industry ASC, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 END
    • The warehouse answers
      STATUS: COMPILES (dry run on the empty schema, no data read)
      COLUMNS: industry, segment, users_count, share_of_industry_users_pct, avg_orders_per_user, avg_order_value_eur
    • InesQuery compiles and returns the expected columns at the industry × segment grain. Submitting now.
    • Ines calls submit
      WITH order_amounts AS (
        SELECT
          o.id AS order_id,
          o.tenant_id,
          o.user_id,
          o.grand_total / er.rate AS grand_total_eur
        FROM orders o
        JOIN exchange_rates er
          ON er.base_code = 'EUR'
          AND er.quote_code = o.currency_code
          AND er.as_of = CAST(o.placed_at AS date)
        WHERE o.placed_at >= DATE '2025-01-01'
          AND o.placed_at < DATE '2026-01-01'
      ),
      flagged AS (
        SELECT
          oa.order_id,
          oa.tenant_id,
          oa.user_id,
          oa.grand_total_eur,
          t.industry,
          CASE WHEN EXISTS (
            SELECT 1 FROM referrals r
            WHERE r.tenant_id = oa.tenant_id AND r.referrer_user_id = oa.user_id
          ) THEN 'referrer' ELSE 'non-referrer' END AS segment
        FROM order_amounts oa
        JOIN tenants t ON t.id = oa.tenant_id
        WHERE t.industry IS NOT NULL
      ),
      user_level AS (
        SELECT industry, segment, tenant_id, user_id, COUNT(*) AS orders_count
        FROM flagged
        GROUP BY industry, segment, tenant_id, user_id
      ),
      industry_user_totals AS (
        SELECT industry, COUNT(*) AS total_users
        FROM (SELECT DISTINCT industry, tenant_id, user_id FROM flagged) x
        GROUP BY industry
      ),
      segment_agg AS (
        SELECT industry, segment,
          COUNT(*) AS users_count,
          AVG(orders_count) AS avg_orders_per_user
        FROM user_level
        GROUP BY industry, segment
      ),
      order_level_agg AS (
        SELECT industry, segment, AVG(grand_total_eur) AS avg_order_value_eur
        FROM flagged
        GROUP BY industry, segment
      )
      SELECT
        s.industry,
        s.segment,
        s.users_count,
        ROUND(100.0 * s.users_count / t.total_users, 2) AS share_of_industry_users_pct,
        ROUND(s.avg_orders_per_user, 2) AS avg_orders_per_user,
        ROUND(o.avg_order_value_eur, 0) AS avg_order_value_eur
      FROM segment_agg s
      JOIN industry_user_totals t ON t.industry = s.industry
      JOIN order_level_agg o ON o.industry = s.industry AND o.segment = s.segment
      ORDER BY s.industry ASC, CASE WHEN s.segment = 'referrer' THEN 0 ELSE 1 END
    • The warehouse answers
      Submitted to tonight's batch. Your work on this request is done.
    • InesSubmitted. Summary of what the report delivers: - **Grain:** one row per `industry` × `segment` (`referrer` / `non-referrer`). - **users_count:** distinct users per segment with ≥1 order placed in 2025 in that industry. - **share_of_industry_users_pct:** that segment's users as a % of all 2025 active shoppers in the industry. - **avg_orders_per_user:** mean 2025 order count per user in the segment. - **avg_order_value_eur:** mean per-order `grand_total` converted to EUR via `exchange_rates` (base EUR, rate as of the order's placed date), rounded to the nearest euro. Noted in the submission: segments are ordered `referrer` before `non-referrer` within each industry, "referrer" status is based on ever appearing as a `referrals.referrer_user_id` for that tenant (not redemption-dependent), and tenants with a null industry were dropped since they have no vertical to report against.