DB Olympics

Queries · q357 · Head of Merchandising · week 2, night 4

Return and Damage Rates for Fragile vs Other Home & Living Categories

“Do fragile homeware categories (cookware, glassware, tableware, decor) see more damage-related returns than other Home & Living categories, supporting the in-transit-breakage theory for the December dip?”

Manager · asked the questionFreya LindgrenHead of Merchandising. Came from a fashion marketplace's catalog team. Responsible for helping merchants present their products well.
Analyst · planned the reportZara AhmedExploratory: looks at the raw detail of an unfamiliar area before aggregating it.
Engineer · wrote the SQLViktorOld-school warehouse engineer: explicit JOIN chains straight to the base tables, derived tables, GROUP BY with CASE pivots, few CTEs.

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

  1. Freya Lindgren writes to Zara Ahmed

    The manager, at the start of week 2

    Subject: Good start — let's dig into the risk areas

    Hi Zara,

    This is really useful, and a few things jumped out that I want to understand better before Friday.

    The Cragsley Outfitters finding worries me most — our #2 merchant by revenue with real quality concentration, and some of those poorly-rated items are still selling briskly. That combination (strong sales, weak ratings, sizable product count) feels like the kind of thing that erodes trust quietly until it doesn't. I'd like to understand it better: is this concentrated in certain kinds of products, has it been building over time, and does it look like it's about to hit sales or is demand just lagging behind reputation?

    Second, the December rating dip needs a clearer story. You flagged it as needing a second month to confirm — I agree, but I'd also like to understand whether there's something explainable behind it (seasonal returns, a particular product push, shipping delays around the holidays) rather than just watching and waiting. If Fennel & Flint and Wiesgrund Wohnen are worth a check-in, I want to go into that conversation knowing roughly what happened.

    Third, I was surprised that going from zero to one image makes such a big difference but more images after that don't. Before I turn that into a merchant talking point, I want to know if we're actually looking at a real presentation effect or just a stand-in for something else — are the zero-image listings systematically different in some way, like older, or a different kind of product?

    Finally, on bundles: you said it's white space but we can't test performance yet because usage is too rare. I'd like to understand it a bit more anecdotally before we design a pilot — among the handful of merchants that do use bundles, is there anything that distinguishes them, even descriptively, from the ones that don't?

    Thanks again — this is exactly the kind of clarity I needed.

    Freya

  2. Zara Ahmed plans the night

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

    Night 3 findings: (1) Wiesgrund Wohnen's December reviews are scattered thinly across 10 different products (mostly 1 review each) rather than concentrated on one bad item — but nearly all of them are fragile homeware: vases, a frying pan, dinner plates, a casserole dish, glassware. That points away from 'systemic quality problem' and toward 'breakage in transit,' which wouldn't show up in on-time-delivery stats (an item can arrive on schedule but shattered). (2) The 3-year December history splits the two merchants clearly: Fennel & Flint shows a real, monotonic 3-year rating decline (4.43 → 3.71 → 3.14) alongside order growth (28 → 45 → 69), consistent with a merchant whose quality control hasn't kept pace with scale; Wiesgrund Wohnen's history is noisier and non-monotonic (4.00 → 3.57 → 3.50, with 2023 already at 28.6% 1-2-star on a tiny sample), more consistent with episodic bad luck than a trend. (3) The bundle-by-vertical split is suspiciously clean — exactly 100% of merchants in six verticals (Beauty, Books & Stationery, Consumer Electronics, Food & Coffee, Home & Living, Jewelry) have made at least one bundle, and exactly 0% in the other five (Apparel & Footwear, both B2B verticals, Pet Supplies, Sports & Outdoor) have made any. A binary split with no partial adoption anywhere is unusual for organic merchant behavior and makes me suspect this may reflect how bundles were seeded/templated per vertical rather than a genuine merchandising choice — I want to check the creation-date distribution before I tell Freya it's a real behavioral pattern. For this final night: (A) check whether bundle creation clusters in one burst (seeding) or spreads out over time (organic), (B) test the fragile-goods-breakage theory with actual return/damage data across Home & Living, and (C) run the same product-level breakdown for Fennel & Flint's December reviews that we did for Wiesgrund, to see if their decline is broad-based or concentrated.

    Return and Damage Rates for Fragile vs Other Home & Living Categories
    Question
    Do fragile homeware categories (cookware, glassware, tableware, decor) see more damage-related returns than other Home & Living categories, supporting the in-transit-breakage theory for the December dip?
    One row per
    product category within tenants in the Home & Living industry
    Columns
    • category_name
    • units_sold_last_12mo
    • return_count
    • return_rate_pct
    • pct_returns_damage_related
  3. Viktor 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 sales AS (
      SELECT
        c.name AS category_name,
        SUM(oi.quantity) AS units_sold
      FROM order_items oi
      JOIN orders o ON o.id = oi.order_id
      JOIN product_variants pv ON pv.id = oi.product_variant_id
      JOIN products p ON p.id = pv.product_id
      JOIN categories c ON c.id = p.primary_category_id
      JOIN tenants t ON t.id = p.tenant_id
      WHERE t.industry = 'Home & Living'
        AND o.placed_at >= DATE '2025-01-01'
        AND o.placed_at < DATE '2026-01-01'
        AND o.status <> 'cancelled'
      GROUP BY c.name
    ),
    returns AS (
      SELECT
        c.name AS category_name,
        COUNT(*) AS return_count,
        SUM(CASE
              WHEN LOWER(orr.reason) LIKE '%damage%'
                OR LOWER(orr.reason) LIKE '%broken%'
                OR LOWER(orr.reason) LIKE '%crack%'
                OR LOWER(orr.reason) LIKE '%chip%'
                OR LOWER(orr.reason) LIKE '%shattered%'
              THEN 1 ELSE 0
            END) AS damage_count
      FROM return_items ri
      JOIN order_returns orr ON orr.id = ri.return_id
      JOIN order_items oi ON oi.id = ri.order_item_id
      JOIN product_variants pv ON pv.id = oi.product_variant_id
      JOIN products p ON p.id = pv.product_id
      JOIN categories c ON c.id = p.primary_category_id
      JOIN tenants t ON t.id = p.tenant_id
      WHERE t.industry = 'Home & Living'
        AND orr.requested_at >= DATE '2025-01-01'
        AND orr.requested_at < DATE '2026-01-01'
      GROUP BY c.name
    )
    SELECT
      s.category_name,
      s.units_sold AS units_sold_last_12mo,
      COALESCE(r.return_count, 0) AS return_count,
      ROUND(COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0), 1) AS return_rate_pct,
      ROUND(COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0), 1) AS pct_returns_damage_related
    FROM sales s
    LEFT JOIN returns r ON r.category_name = s.category_name
    ORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASC

    “Query compiles cleanly with the expected columns. Submitting.”

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

    “Submitted. Summary of the approach: - Grain: one row per product category name (rolled up across all tenants in the Home & Living industry), since the report columns only carry category_name with no tenant breakdown. - Sales: units sold = sum of order_items.quantity for orders placed in 2025 with status not cancelled, joined through variant → product → primary category → tenant (industry filter). - Returns: counted via return_items joined to order_returns (filtered on requested_at in 2025) and back to the same product/category chain. - Damage share: flagged using a case-insensitive LIKE match on order_returns.reason for damage/broken/crack/chip/shattered, as a percentage of that category's own returns. - Categories with zero units sold in the window are naturally excluded (inner-joined via the sales CTE) since a return rate would be undefined for them — noted in the submit note.”

  4. The report comes back overnight

    As Zara Ahmed saw it, from the small dataset the agents worked on

    category_name | units_sold_last_12mo | return_count | return_rate_pct | pct_returns_damage_related
    --------------+----------------------+--------------+-----------------+---------------------------
    Bedding       |                  387 |           56 |            14.5 |                        3.6
    Decor         |                  675 |           49 |             7.3 |                       26.5
    Towels        |                  379 |           27 |             7.1 |                        3.7
    Furniture     |                  148 |           10 |             6.8 |                       40.0
    Cookware      |                  599 |           38 |             6.3 |                       15.8
    Appliances    |                  260 |           15 |             5.8 |                       26.7
    Lighting      |                  207 |           12 |             5.8 |                       25.0
    Textiles      |                  564 |           31 |             5.5 |                        9.7
    Glassware     |                  304 |           15 |             4.9 |                       26.7
    Tableware     |                  226 |           10 |             4.4 |                       30.0
    Bathroom      |                   20 |            0 |             0.0 |                       NULL
    Bedroom       |                    1 |            0 |             0.0 |                       NULL
    (12 rows)
  5. What came of it

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

    It builds on:

  6. It becomes benchmark query q357

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

    • numericsdocs/NUMERICS.md: rounding removed; results keep full precision
    • made explicita selected t.col gets AS col, its standard name made explicit
    • determinismthe standard leaves the place of NULLs in a sort to the implementation: NULLS LAST ascending, NULLS FIRST descending, as in the reference results
    The benchmark text, against the submitted SQL
    WITH sales AS (  SELECT    c.name AS category_name,    SUM(oi.quantity) AS units_sold  FROM order_items oi  JOIN orders o ON o.id = oi.order_id  JOIN product_variants pv ON pv.id = oi.product_variant_id  JOIN products p ON p.id = pv.product_id  JOIN categories c ON c.id = p.primary_category_id  JOIN tenants t ON t.id = p.tenant_id  WHERE t.industry = 'Home & Living'    AND o.placed_at >= DATE '2025-01-01'    AND o.placed_at < DATE '2026-01-01'    AND o.status <> 'cancelled'  GROUP BY c.name),returns AS (  SELECT    c.name AS category_name,    COUNT(*) AS return_count,    SUM(CASE          WHEN LOWER(orr.reason) LIKE '%damage%'            OR LOWER(orr.reason) LIKE '%broken%'            OR LOWER(orr.reason) LIKE '%crack%'            OR LOWER(orr.reason) LIKE '%chip%'            OR LOWER(orr.reason) LIKE '%shattered%'          THEN 1 ELSE 0        END) AS damage_count  FROM return_items ri  JOIN order_returns orr ON orr.id = ri.return_id  JOIN order_items oi ON oi.id = ri.order_item_id  JOIN product_variants pv ON pv.id = oi.product_variant_id  JOIN products p ON p.id = pv.product_id  JOIN categories c ON c.id = p.primary_category_id  JOIN tenants t ON t.id = p.tenant_id  WHERE t.industry = 'Home & Living'    AND orr.requested_at >= DATE '2025-01-01'    AND orr.requested_at < DATE '2026-01-01'  GROUP BY c.name)SELECT  s.category_name,  s.category_name AS category_name,  s.units_sold AS units_sold_last_12mo,  COALESCE(r.return_count, 0) AS return_count,  ROUND(COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0), 1) AS return_rate_pct,  ROUND(COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0), 1) AS pct_returns_damage_related  COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0) AS return_rate_pct,  COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0) AS pct_returns_damage_relatedFROM sales sLEFT JOIN returns r ON r.category_name = s.category_nameORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASCORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASC NULLS LAST
    WITH sales AS (
      SELECT
        c.name AS category_name,
        SUM(oi.quantity) AS units_sold
      FROM order_items oi
      JOIN orders o ON o.id = oi.order_id
      JOIN product_variants pv ON pv.id = oi.product_variant_id
      JOIN products p ON p.id = pv.product_id
      JOIN categories c ON c.id = p.primary_category_id
      JOIN tenants t ON t.id = p.tenant_id
      WHERE t.industry = 'Home & Living'
        AND o.placed_at >= DATE '2025-01-01'
        AND o.placed_at < DATE '2026-01-01'
        AND o.status <> 'cancelled'
      GROUP BY c.name
    ),
    returns AS (
      SELECT
        c.name AS category_name,
        COUNT(*) AS return_count,
        SUM(CASE
              WHEN LOWER(orr.reason) LIKE '%damage%'
                OR LOWER(orr.reason) LIKE '%broken%'
                OR LOWER(orr.reason) LIKE '%crack%'
                OR LOWER(orr.reason) LIKE '%chip%'
                OR LOWER(orr.reason) LIKE '%shattered%'
              THEN 1 ELSE 0
            END) AS damage_count
      FROM return_items ri
      JOIN order_returns orr ON orr.id = ri.return_id
      JOIN order_items oi ON oi.id = ri.order_item_id
      JOIN product_variants pv ON pv.id = oi.product_variant_id
      JOIN products p ON p.id = pv.product_id
      JOIN categories c ON c.id = p.primary_category_id
      JOIN tenants t ON t.id = p.tenant_id
      WHERE t.industry = 'Home & Living'
        AND orr.requested_at >= DATE '2025-01-01'
        AND orr.requested_at < DATE '2026-01-01'
      GROUP BY c.name
    )
    SELECT
      s.category_name AS category_name,
      s.units_sold AS units_sold_last_12mo,
      COALESCE(r.return_count, 0) AS return_count,
      COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0) AS return_rate_pct,
      COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0) AS pct_returns_damage_related
    FROM sales s
    LEFT JOIN returns r ON r.category_name = s.category_name
    ORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASC NULLS LAST
    100 ms1 sHyper194 msDuckDB354 msGizmoSQL394 msclickhouse_brew449 msFirebolt545 msDataFusion859 msClickHouse392 ms
  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

    Viktor's whole session, 7 turns
    • The request, as Viktor received it
      Report request from Zara Ahmed (analyst for the Head of Merchandising):
      
      Title: Return and Damage Rates for Fragile vs Other Home & Living Categories
      Question: Do fragile homeware categories (cookware, glassware, tableware, decor) see more damage-related returns than other Home & Living categories, supporting the in-transit-breakage theory for the December dip?
      Grain: one row per product category within tenants in the Home & Living industry
      Columns:
      - category_name
      - units_sold_last_12mo
      - return_count
      - return_rate_pct
      - pct_returns_damage_related
      Details: Scope to products whose tenant has industry = 'Home & Living'. units_sold_last_12mo = sum of order_items.quantity for that category's products from orders placed 2025-01-01 to 2025-12-31, status not cancelled. return_count = count of return_items (joined via order_items to the category's products) whose parent order_returns.requested_at falls in the same 2025-01-01 to 2025-12-31 window. return_rate_pct = return_count / units_sold_last_12mo * 100, rounded to 1 decimal. pct_returns_damage_related = share of those return_items whose order_returns.reason (case-insensitive) contains any of 'damage', 'broken', 'crack', 'chip', or 'shattered', rounded to 1 decimal. Order by return_rate_pct descending, tie-break by category_name.
      
      Check your query with the warehouse's dry_run tool, then hand it in with submit.
    • Viktor calls dry_run
      WITH sales AS (
        SELECT
          c.name AS category_name,
          SUM(oi.quantity) AS units_sold
        FROM order_items oi
        JOIN orders o ON o.id = oi.order_id
        JOIN product_variants pv ON pv.id = oi.product_variant_id
        JOIN products p ON p.id = pv.product_id
        JOIN categories c ON c.id = p.primary_category_id
        JOIN tenants t ON t.id = p.tenant_id
        WHERE t.industry = 'Home & Living'
          AND o.placed_at >= DATE '2025-01-01'
          AND o.placed_at < DATE '2026-01-01'
          AND o.status <> 'cancelled'
        GROUP BY c.name
      ),
      returns AS (
        SELECT
          c.name AS category_name,
          COUNT(*) AS return_count,
          SUM(CASE
                WHEN LOWER(orr.reason) LIKE '%damage%'
                  OR LOWER(orr.reason) LIKE '%broken%'
                  OR LOWER(orr.reason) LIKE '%crack%'
                  OR LOWER(orr.reason) LIKE '%chip%'
                  OR LOWER(orr.reason) LIKE '%shattered%'
                THEN 1 ELSE 0
              END) AS damage_count
        FROM return_items ri
        JOIN order_returns orr ON orr.id = ri.return_id
        JOIN order_items oi ON oi.id = ri.order_item_id
        JOIN product_variants pv ON pv.id = oi.product_variant_id
        JOIN products p ON p.id = pv.product_id
        JOIN categories c ON c.id = p.primary_category_id
        JOIN tenants t ON t.id = p.tenant_id
        WHERE t.industry = 'Home & Living'
          AND orr.requested_at >= DATE '2025-01-01'
          AND orr.requested_at < DATE '2026-01-01'
        GROUP BY c.name
      )
      SELECT
        s.category_name,
        s.units_sold AS units_sold_last_12mo,
        COALESCE(r.return_count, 0) AS return_count,
        ROUND(COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0), 1) AS return_rate_pct,
        ROUND(COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0), 1) AS pct_returns_damage_related
      FROM sales s
      LEFT JOIN returns r ON r.category_name = s.category_name
      ORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASC
    • The warehouse answers
      STATUS: COMPILES (dry run on the empty schema, no data read)
      COLUMNS: category_name, units_sold_last_12mo, return_count, return_rate_pct, pct_returns_damage_related
    • ViktorQuery compiles cleanly with the expected columns. Submitting.
    • Viktor calls submit
      WITH sales AS (
        SELECT
          c.name AS category_name,
          SUM(oi.quantity) AS units_sold
        FROM order_items oi
        JOIN orders o ON o.id = oi.order_id
        JOIN product_variants pv ON pv.id = oi.product_variant_id
        JOIN products p ON p.id = pv.product_id
        JOIN categories c ON c.id = p.primary_category_id
        JOIN tenants t ON t.id = p.tenant_id
        WHERE t.industry = 'Home & Living'
          AND o.placed_at >= DATE '2025-01-01'
          AND o.placed_at < DATE '2026-01-01'
          AND o.status <> 'cancelled'
        GROUP BY c.name
      ),
      returns AS (
        SELECT
          c.name AS category_name,
          COUNT(*) AS return_count,
          SUM(CASE
                WHEN LOWER(orr.reason) LIKE '%damage%'
                  OR LOWER(orr.reason) LIKE '%broken%'
                  OR LOWER(orr.reason) LIKE '%crack%'
                  OR LOWER(orr.reason) LIKE '%chip%'
                  OR LOWER(orr.reason) LIKE '%shattered%'
                THEN 1 ELSE 0
              END) AS damage_count
        FROM return_items ri
        JOIN order_returns orr ON orr.id = ri.return_id
        JOIN order_items oi ON oi.id = ri.order_item_id
        JOIN product_variants pv ON pv.id = oi.product_variant_id
        JOIN products p ON p.id = pv.product_id
        JOIN categories c ON c.id = p.primary_category_id
        JOIN tenants t ON t.id = p.tenant_id
        WHERE t.industry = 'Home & Living'
          AND orr.requested_at >= DATE '2025-01-01'
          AND orr.requested_at < DATE '2026-01-01'
        GROUP BY c.name
      )
      SELECT
        s.category_name,
        s.units_sold AS units_sold_last_12mo,
        COALESCE(r.return_count, 0) AS return_count,
        ROUND(COALESCE(r.return_count, 0) * 100.0 / NULLIF(s.units_sold, 0), 1) AS return_rate_pct,
        ROUND(COALESCE(r.damage_count, 0) * 100.0 / NULLIF(r.return_count, 0), 1) AS pct_returns_damage_related
      FROM sales s
      LEFT JOIN returns r ON r.category_name = s.category_name
      ORDER BY return_rate_pct DESC NULLS LAST, s.category_name ASC
    • The warehouse answers
      Submitted to tonight's batch. Your work on this request is done.
    • ViktorSubmitted. Summary of the approach: - **Grain**: one row per product category name (rolled up across all tenants in the Home & Living industry), since the report columns only carry `category_name` with no tenant breakdown. - **Sales**: units sold = sum of `order_items.quantity` for orders placed in 2025 with status not `cancelled`, joined through variant → product → primary category → tenant (industry filter). - **Returns**: counted via `return_items` joined to `order_returns` (filtered on `requested_at` in 2025) and back to the same product/category chain. - **Damage share**: flagged using a case-insensitive `LIKE` match on `order_returns.reason` for damage/broken/crack/chip/shattered, as a percentage of that category's own returns. - Categories with zero units sold in the window are naturally excluded (inner-joined via the `sales` CTE) since a return rate would be undefined for them — noted in the submit note.