DB Olympics

Queries · q021 · Chief Financial Officer · week 1, night 3

Apparel & Footwear Refund Rate Trend by Quarter, 2024-2025

“Within the outlier Apparel & Footwear vertical, is the elevated refund rate structural/stable or getting worse over time, and how does it compare to the company average each quarter?”

Manager · asked the questionTobias LindqvistChief Financial Officer. New this month, previously finance director at a retailer. Preparing the 2025 annual accounts and the 2026 budget.
Analyst · planned the reportKofi MensahHypothesis-driven: states what he expects and designs reports that would prove him wrong.
Engineer · wrote the SQLBeaWrites SQL the way the company's BI tool generates it: verbose fully qualified aliases (t0, t1, ...), a subquery per measure joined back on the grain keys, COALESCE everywhere.

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

  1. Tobias Lindqvist writes to Kofi Mensah

    The manager, at the start of week 1

    Subject: Finding my bearings – first set of questions for the week

    Hi Kofi,

    Good to be working with you. I'm still building my mental map of the business, so I'd rather ask a few broad questions well than a lot of narrow ones badly. Given the slot budget, here's what I'd prioritize this week, roughly in order:

    1. How did we actually do in 2025, and where is the money coming from? I want to see our own revenue split between the subscription/plan fees and the payment-processing fees, over the year, and ideally how that's trending month to month. This is the backbone of the annual accounts narrative and will shape how I talk about 2025 to the board.
    2. How concentrated is our business in a few large merchants, and how healthy are they? I keep hearing "a handful of large merchants drive most of the volume" — I'd like to understand who they are, how much of our gross volume and revenue they represent, and whether that concentration is growing or shrinking. This matters for risk assessment going into the budget.
    3. What do refunds and returns look like across the merchant base? I want a sense of refund rates — overall and whether certain verticals or merchants are outliers — since this affects both our net revenue and how much cash we actually end up paying out.
    4. How exposed are we to currency movements? Merchants bill in their own currencies, and shoppers come from ~40 countries. I'd like a picture of how our volume and revenue break down by currency, so I can gauge our FX exposure for the 2026 budget and think about whether we need any hedging conversation.
    5. Are our B2B merchants paying us and their own customers on time? I know a few of our merchants are wholesalers running on B2B terms. I'd like to understand how their receivables look — how much is outstanding and how overdue it tends to get — since this could be a real cash-flow risk if it's worse than I'd expect.

    For this week, let's focus on #1 and #2 — those are the two I most need before I can speak credibly about 2025 and the 2026 budget. If there's room, #3 would be next; #4 and #5 can wait for a follow-up week if slots are tight.

    Let me know if any of these need me to narrow scope further before you brief the data engineers.

    Thanks, Tobias

  2. Kofi Mensah plans the night

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

    The currency reconciliation report is the key finding tonight: payout_count_missing_fx_rate is 0 for every currency, so FX coverage is complete — my "inner join dropping unmatched currencies" hypothesis was wrong. But summing the reconciliation report's own gross_volume_eur across currencies gives €3,972,988 and fee_revenue_eur gives €93,583 — both match Night 1's Report 3 total almost to the cent. That confirms the TRUE 2025 totals, and proves Night 1's Report 1 (monthly trend: €1.99M gross / €53.2k fee) was wrong by a different mechanism than I guessed — not missing FX matches, but something in how that specific query aggregated/converted by month (gross was off by ~2.0x, fee only by ~1.76x, so it's not a uniform "half the rows missing" bug either, more likely a currency-conversion-direction or grouping error localized to that query). Rather than guess further, I'm asking for the monthly report to be rebuilt using the exact validated per-payout conversion method from tonight's reconciliation report, with an explicit annual TOTAL row so it self-checks against the €3,972,988 / €93,583 figures I now trust. This is the top priority tonight since it underpins the board-facing 2025 revenue narrative.

    On refunds: Apparel & Footwear stands out hard at ~20.8% refund rate, 3-6x every other vertical, and it's broad-based across apparel merchants (not just one outlier per Report 3), so I don't think it's a data artifact — apparel/fashion e-commerce genuinely runs high return rates. Still, since this affects net revenue and cash payouts (Tobias's framing), I want to know if it's stable or worsening, especially given the Nov/Dec volume spike we saw in gross volume. I'm using my remaining two slots for a company-wide quarterly refund-rate trend and an Apparel-specific quarterly trend, both 2024 vs 2025, to see direction of travel before I write the memo.

    Apparel & Footwear Refund Rate Trend by Quarter, 2024-2025
    Question
    Within the outlier Apparel & Footwear vertical, is the elevated refund rate structural/stable or getting worse over time, and how does it compare to the company average each quarter?
    One row per
    one calendar quarter (2024-Q1 through 2025-Q4), restricted to the Apparel & Footwear vertical
    Columns
    • quarter
    • merchant_count (Apparel & Footwear tenants with qualifying payments that quarter)
    • payment_count
    • gross_captured_eur
    • amount_refunded_eur
    • refund_rate_pct
    • company_avg_refund_rate_pct (all verticals, same quarter, for comparison)
  3. Bea 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 quarters AS (
      SELECT DISTINCT year_num, quarter_num
      FROM calendar_days
      WHERE year_num IN (2024, 2025)
    ),
    exch AS (
      SELECT quote_code, as_of, rate
      FROM exchange_rates
      WHERE base_code = 'EUR'
    ),
    payment_eur AS (
      SELECT
        p.id AS payment_id,
        p.tenant_id,
        t.industry,
        cd.year_num,
        cd.quarter_num,
        p.amount / er.rate AS amount_eur,
        p.amount_refunded / er.rate AS amount_refunded_eur
      FROM payments p
      JOIN tenants t ON t.id = p.tenant_id
      JOIN calendar_days cd ON cd.calendar_date = CAST(p.captured_at AS date)
      JOIN exch er ON er.quote_code = p.currency_code AND er.as_of = cd.calendar_date
      WHERE p.status IN ('captured','partially_refunded','refunded')
        AND p.captured_at >= TIMESTAMP '2024-01-01'
        AND p.captured_at < TIMESTAMP '2026-01-01'
    ),
    apparel_agg AS (
      SELECT year_num, quarter_num,
        COUNT(DISTINCT tenant_id) AS merchant_count,
        COUNT(*) AS payment_count,
        SUM(amount_eur) AS gross_captured_eur,
        SUM(amount_refunded_eur) AS amount_refunded_eur
      FROM payment_eur
      WHERE industry = 'Apparel & Footwear'
      GROUP BY year_num, quarter_num
    ),
    company_agg AS (
      SELECT year_num, quarter_num,
        SUM(amount_eur) AS gross_captured_eur,
        SUM(amount_refunded_eur) AS amount_refunded_eur
      FROM payment_eur
      GROUP BY year_num, quarter_num
    )
    SELECT
      q.year_num || '-Q' || q.quarter_num AS quarter,
      COALESCE(a.merchant_count, 0) AS merchant_count,
      COALESCE(a.payment_count, 0) AS payment_count,
      ROUND(COALESCE(a.gross_captured_eur,0),2) AS gross_captured_eur,
      ROUND(COALESCE(a.amount_refunded_eur,0),2) AS amount_refunded_eur,
      ROUND(CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END, 2) AS refund_rate_pct,
      ROUND(CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END, 2) AS company_avg_refund_rate_pct
    FROM quarters q
    LEFT JOIN apparel_agg a ON a.year_num = q.year_num AND a.quarter_num = q.quarter_num
    LEFT JOIN company_agg c ON c.year_num = q.year_num AND c.quarter_num = q.quarter_num
    ORDER BY q.year_num, q.quarter_num

    “Query compiles and returns the expected 7 columns at quarterly grain. Submitting.”

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

    “Submitted. The report builds an 8-row quarterly series (2024-Q1 to 2025-Q2025-Q4) with Apparel & Footwear's merchant count, payment count, gross captured, refunds, and refund rate, alongside the volume-weighted company-wide refund rate for the same quarter — letting Kofi see directly whether the apparel gap is widening, narrowing, or flat.”

  4. The report comes back overnight

    As Kofi Mensah saw it, from the small dataset the agents worked on

    quarter | merchant_count | payment_count | gross_captured_eur | amount_refunded_eur | refund_rate_pct | company_avg_refund_rate_pct
    --------+----------------+---------------+--------------------+---------------------+-----------------+----------------------------
    2024-Q1 |              7 |           894 |          197075.62 |             41567.9 |           21.09 |                       10.58
    2024-Q2 |              8 |           922 |          181654.82 |            41182.07 |           22.67 |                       10.48
    2024-Q3 |              9 |           988 |          168971.48 |            35312.27 |            20.9 |                         8.4
    2024-Q4 |              9 |          1975 |          386950.72 |            99873.88 |           25.81 |                       14.13
    2025-Q1 |             11 |          1150 |          216621.44 |            44831.18 |            20.7 |                        7.77
    2025-Q2 |             11 |          1169 |          198881.22 |            44578.08 |           22.41 |                       10.66
    2025-Q3 |             11 |          1212 |           192047.6 |            42818.11 |            22.3 |                       13.45
    2025-Q4 |             11 |          2298 |          470544.84 |            91672.62 |           19.48 |                       11.92
    (8 rows)
  5. What came of it

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

    Later queries that build on this report:

    It builds on:

  6. It becomes benchmark query q021

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

    • numericsdocs/NUMERICS.md: rounding removed; results keep full precision
    • numericsdocs/NUMERICS.md: x / exchange rate cast to NUMERIC(18,6) (2×)
    • made explicita selected t.col gets AS col, its standard name made explicit (4×)
    • 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 quarters AS (  SELECT DISTINCT year_num, quarter_num  FROM calendar_days  WHERE year_num IN (2024, 2025)),exch AS (  SELECT quote_code, as_of, rate  FROM exchange_rates  WHERE base_code = 'EUR'),payment_eur AS (  SELECT    p.id AS payment_id,    p.tenant_id,    t.industry,    cd.year_num,    cd.quarter_num,    p.amount / er.rate AS amount_eur,    p.amount_refunded / er.rate AS amount_refunded_eur    p.tenant_id AS tenant_id,    t.industry AS industry,    cd.year_num AS year_num,    cd.quarter_num AS quarter_num,    CAST(p.amount / er.rate AS NUMERIC(18,6)) AS amount_eur,    CAST(p.amount_refunded / er.rate AS NUMERIC(18,6)) AS amount_refunded_eur  FROM payments p  JOIN tenants t ON t.id = p.tenant_id  JOIN calendar_days cd ON cd.calendar_date = CAST(p.captured_at AS date)  JOIN exch er ON er.quote_code = p.currency_code AND er.as_of = cd.calendar_date  WHERE p.status IN ('captured','partially_refunded','refunded')    AND p.captured_at >= TIMESTAMP '2024-01-01'    AND p.captured_at < TIMESTAMP '2026-01-01'),apparel_agg AS (  SELECT year_num, quarter_num,    COUNT(DISTINCT tenant_id) AS merchant_count,    COUNT(*) AS payment_count,    SUM(amount_eur) AS gross_captured_eur,    SUM(amount_refunded_eur) AS amount_refunded_eur  FROM payment_eur  WHERE industry = 'Apparel & Footwear'  GROUP BY year_num, quarter_num),company_agg AS (  SELECT year_num, quarter_num,    SUM(amount_eur) AS gross_captured_eur,    SUM(amount_refunded_eur) AS amount_refunded_eur  FROM payment_eur  GROUP BY year_num, quarter_num)SELECT  q.year_num || '-Q' || q.quarter_num AS quarter,  COALESCE(a.merchant_count, 0) AS merchant_count,  COALESCE(a.payment_count, 0) AS payment_count,  ROUND(COALESCE(a.gross_captured_eur,0),2) AS gross_captured_eur,  ROUND(COALESCE(a.amount_refunded_eur,0),2) AS amount_refunded_eur,  ROUND(CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END, 2) AS refund_rate_pct,  ROUND(CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END, 2) AS company_avg_refund_rate_pct  COALESCE(a.gross_captured_eur,0) AS gross_captured_eur,  COALESCE(a.amount_refunded_eur,0) AS amount_refunded_eur,  CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END AS refund_rate_pct,  CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END AS company_avg_refund_rate_pctFROM quarters qLEFT JOIN apparel_agg a ON a.year_num = q.year_num AND a.quarter_num = q.quarter_numLEFT JOIN company_agg c ON c.year_num = q.year_num AND c.quarter_num = q.quarter_numORDER BY q.year_num, q.quarter_numORDER BY q.year_num NULLS LAST, q.quarter_num NULLS LAST
    WITH quarters AS (
      SELECT DISTINCT year_num, quarter_num
      FROM calendar_days
      WHERE year_num IN (2024, 2025)
    ),
    exch AS (
      SELECT quote_code, as_of, rate
      FROM exchange_rates
      WHERE base_code = 'EUR'
    ),
    payment_eur AS (
      SELECT
        p.id AS payment_id,
        p.tenant_id AS tenant_id,
        t.industry AS industry,
        cd.year_num AS year_num,
        cd.quarter_num AS quarter_num,
        CAST(p.amount / er.rate AS NUMERIC(18,6)) AS amount_eur,
        CAST(p.amount_refunded / er.rate AS NUMERIC(18,6)) AS amount_refunded_eur
      FROM payments p
      JOIN tenants t ON t.id = p.tenant_id
      JOIN calendar_days cd ON cd.calendar_date = CAST(p.captured_at AS date)
      JOIN exch er ON er.quote_code = p.currency_code AND er.as_of = cd.calendar_date
      WHERE p.status IN ('captured','partially_refunded','refunded')
        AND p.captured_at >= TIMESTAMP '2024-01-01'
        AND p.captured_at < TIMESTAMP '2026-01-01'
    ),
    apparel_agg AS (
      SELECT year_num, quarter_num,
        COUNT(DISTINCT tenant_id) AS merchant_count,
        COUNT(*) AS payment_count,
        SUM(amount_eur) AS gross_captured_eur,
        SUM(amount_refunded_eur) AS amount_refunded_eur
      FROM payment_eur
      WHERE industry = 'Apparel & Footwear'
      GROUP BY year_num, quarter_num
    ),
    company_agg AS (
      SELECT year_num, quarter_num,
        SUM(amount_eur) AS gross_captured_eur,
        SUM(amount_refunded_eur) AS amount_refunded_eur
      FROM payment_eur
      GROUP BY year_num, quarter_num
    )
    SELECT
      q.year_num || '-Q' || q.quarter_num AS quarter,
      COALESCE(a.merchant_count, 0) AS merchant_count,
      COALESCE(a.payment_count, 0) AS payment_count,
      COALESCE(a.gross_captured_eur,0) AS gross_captured_eur,
      COALESCE(a.amount_refunded_eur,0) AS amount_refunded_eur,
      CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END AS refund_rate_pct,
      CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END AS company_avg_refund_rate_pct
    FROM quarters q
    LEFT JOIN apparel_agg a ON a.year_num = q.year_num AND a.quarter_num = q.quarter_num
    LEFT JOIN company_agg c ON c.year_num = q.year_num AND c.quarter_num = q.quarter_num
    ORDER BY q.year_num NULLS LAST, q.quarter_num NULLS LAST
    100 ms1 s10 sHyper191 msDuckDB2.37 sGizmoSQL1.86 sclickhouse_brew489 msFirebolterrorDataFusion248 msClickHouseerror
    • Firebolt{ "errors": [ { "description": "Line 18, Column 19: 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": "514172f5-f6fb-4330-b250-74f08e21eb94", "query_lab
    • ClickHouseCode: 69. DB::Exception: Decimal result's scale is less than argument's one: while executing function divide on arguments __table5.amount Decimal(14, 4) Decimal64(size = 0), __table8.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

    Bea's whole session, 7 turns
    • The request, as Bea received it
      Report request from Kofi Mensah (analyst for the Chief Financial Officer):
      
      Title: Apparel & Footwear Refund Rate Trend by Quarter, 2024-2025
      Question: Within the outlier Apparel & Footwear vertical, is the elevated refund rate structural/stable or getting worse over time, and how does it compare to the company average each quarter?
      Grain: one calendar quarter (2024-Q1 through 2025-Q4), restricted to the Apparel & Footwear vertical
      Columns:
      - quarter
      - merchant_count (Apparel & Footwear tenants with qualifying payments that quarter)
      - payment_count
      - gross_captured_eur
      - amount_refunded_eur
      - refund_rate_pct
      - company_avg_refund_rate_pct (all verticals, same quarter, for comparison)
      Details: Source: payments joined to tenants where tenants.industry = 'Apparel & Footwear', filtered to status reflecting captured/refunded/partially_refunded with captured_at between 2024-01-01 and 2025-12-31, converted to EUR the same way as the company-wide refund trend report (exchange_rates matched on currency_code and date(captured_at)). Group by calendar quarter. The company_avg_refund_rate_pct column should be the all-tenant, all-vertical refund rate for that same quarter (volume-weighted: total amount_refunded_eur / total gross_captured_eur across every tenant), to show the gap each quarter. Order chronologically 2024-Q1 to 2025-Q4 (8 rows).
      
      Check your query with the warehouse's dry_run tool, then hand it in with submit.
    • Bea calls dry_run
      WITH quarters AS (
        SELECT DISTINCT year_num, quarter_num
        FROM calendar_days
        WHERE year_num IN (2024, 2025)
      ),
      exch AS (
        SELECT quote_code, as_of, rate
        FROM exchange_rates
        WHERE base_code = 'EUR'
      ),
      payment_eur AS (
        SELECT
          p.id AS payment_id,
          p.tenant_id,
          t.industry,
          cd.year_num,
          cd.quarter_num,
          p.amount / er.rate AS amount_eur,
          p.amount_refunded / er.rate AS amount_refunded_eur
        FROM payments p
        JOIN tenants t ON t.id = p.tenant_id
        JOIN calendar_days cd ON cd.calendar_date = CAST(p.captured_at AS date)
        JOIN exch er ON er.quote_code = p.currency_code AND er.as_of = cd.calendar_date
        WHERE p.status IN ('captured','partially_refunded','refunded')
          AND p.captured_at >= TIMESTAMP '2024-01-01'
          AND p.captured_at < TIMESTAMP '2026-01-01'
      ),
      apparel_agg AS (
        SELECT year_num, quarter_num,
          COUNT(DISTINCT tenant_id) AS merchant_count,
          COUNT(*) AS payment_count,
          SUM(amount_eur) AS gross_captured_eur,
          SUM(amount_refunded_eur) AS amount_refunded_eur
        FROM payment_eur
        WHERE industry = 'Apparel & Footwear'
        GROUP BY year_num, quarter_num
      ),
      company_agg AS (
        SELECT year_num, quarter_num,
          SUM(amount_eur) AS gross_captured_eur,
          SUM(amount_refunded_eur) AS amount_refunded_eur
        FROM payment_eur
        GROUP BY year_num, quarter_num
      )
      SELECT
        q.year_num || '-Q' || q.quarter_num AS quarter,
        COALESCE(a.merchant_count, 0) AS merchant_count,
        COALESCE(a.payment_count, 0) AS payment_count,
        ROUND(COALESCE(a.gross_captured_eur,0),2) AS gross_captured_eur,
        ROUND(COALESCE(a.amount_refunded_eur,0),2) AS amount_refunded_eur,
        ROUND(CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END, 2) AS refund_rate_pct,
        ROUND(CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END, 2) AS company_avg_refund_rate_pct
      FROM quarters q
      LEFT JOIN apparel_agg a ON a.year_num = q.year_num AND a.quarter_num = q.quarter_num
      LEFT JOIN company_agg c ON c.year_num = q.year_num AND c.quarter_num = q.quarter_num
      ORDER BY q.year_num, q.quarter_num
    • The warehouse answers
      STATUS: COMPILES (dry run on the empty schema, no data read)
      COLUMNS: quarter, merchant_count, payment_count, gross_captured_eur, amount_refunded_eur, refund_rate_pct, company_avg_refund_rate_pct
    • BeaQuery compiles and returns the expected 7 columns at quarterly grain. Submitting.
    • Bea calls submit
      WITH quarters AS (
        SELECT DISTINCT year_num, quarter_num
        FROM calendar_days
        WHERE year_num IN (2024, 2025)
      ),
      exch AS (
        SELECT quote_code, as_of, rate
        FROM exchange_rates
        WHERE base_code = 'EUR'
      ),
      payment_eur AS (
        SELECT
          p.id AS payment_id,
          p.tenant_id,
          t.industry,
          cd.year_num,
          cd.quarter_num,
          p.amount / er.rate AS amount_eur,
          p.amount_refunded / er.rate AS amount_refunded_eur
        FROM payments p
        JOIN tenants t ON t.id = p.tenant_id
        JOIN calendar_days cd ON cd.calendar_date = CAST(p.captured_at AS date)
        JOIN exch er ON er.quote_code = p.currency_code AND er.as_of = cd.calendar_date
        WHERE p.status IN ('captured','partially_refunded','refunded')
          AND p.captured_at >= TIMESTAMP '2024-01-01'
          AND p.captured_at < TIMESTAMP '2026-01-01'
      ),
      apparel_agg AS (
        SELECT year_num, quarter_num,
          COUNT(DISTINCT tenant_id) AS merchant_count,
          COUNT(*) AS payment_count,
          SUM(amount_eur) AS gross_captured_eur,
          SUM(amount_refunded_eur) AS amount_refunded_eur
        FROM payment_eur
        WHERE industry = 'Apparel & Footwear'
        GROUP BY year_num, quarter_num
      ),
      company_agg AS (
        SELECT year_num, quarter_num,
          SUM(amount_eur) AS gross_captured_eur,
          SUM(amount_refunded_eur) AS amount_refunded_eur
        FROM payment_eur
        GROUP BY year_num, quarter_num
      )
      SELECT
        q.year_num || '-Q' || q.quarter_num AS quarter,
        COALESCE(a.merchant_count, 0) AS merchant_count,
        COALESCE(a.payment_count, 0) AS payment_count,
        ROUND(COALESCE(a.gross_captured_eur,0),2) AS gross_captured_eur,
        ROUND(COALESCE(a.amount_refunded_eur,0),2) AS amount_refunded_eur,
        ROUND(CASE WHEN COALESCE(a.gross_captured_eur,0) = 0 THEN NULL ELSE a.amount_refunded_eur / a.gross_captured_eur * 100 END, 2) AS refund_rate_pct,
        ROUND(CASE WHEN COALESCE(c.gross_captured_eur,0) = 0 THEN NULL ELSE c.amount_refunded_eur / c.gross_captured_eur * 100 END, 2) AS company_avg_refund_rate_pct
      FROM quarters q
      LEFT JOIN apparel_agg a ON a.year_num = q.year_num AND a.quarter_num = q.quarter_num
      LEFT JOIN company_agg c ON c.year_num = q.year_num AND c.quarter_num = q.quarter_num
      ORDER BY q.year_num, q.quarter_num
    • The warehouse answers
      Submitted to tonight's batch. Your work on this request is done.
    • BeaSubmitted. The report builds an 8-row quarterly series (2024-Q1 to 2025-Q2025-Q4) with Apparel & Footwear's merchant count, payment count, gross captured, refunds, and refund rate, alongside the volume-weighted company-wide refund rate for the same quarter — letting Kofi see directly whether the apparel gap is widening, narrowing, or flat.