DB Olympics

Queries · q298 · VP Product · week 2, night 4

Weekday-matched cart conversion baseline for Cragsley Outfitters, Sep 29 – Nov 25 2025

“Were Nov 24-25 (the start of the reminder-email outage) unusually low for their day of week, or within normal week-to-week variation?”

Manager · asked the questionJonas FeldVP Product. Joined from a mobile-first retailer. Deciding the 2026 roadmap.
Analyst · planned the reportEmeka ObiCustomer-centric: follows cohorts of shoppers or merchants over time.
Engineer · wrote the SQLOmarPragmatic: the shortest correct query, aggregates first and joins dimensions afterwards, FILTER clauses for conditional counts.

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

  1. A business event lands on the VP Product's desk

    Week 1

    We are redesigning the shopper journey for 2026. We need to understand the whole path, from the first visit to checkout, delivery, returns and the next purchase, and where shoppers drop out and why.

  2. Jonas Feld writes to Emeka Obi

    The manager, at the start of week 2

    Subject: Good start — let's dig into the cart leak

    Emeka, this is exactly the kind of clarity I needed. The cart-stage bleed is the headline, and I agree we should lead with it — but a two-thirds drop-off that lingers for days, converting at under 20%, isn't something we can act on until we know why people stall. "Add cart recovery emails" is a guess until we understand the shape of the hesitation. That's my main ask for this week.

    I also want to flag one thing before we build a roadmap slide on repeat purchase and returns: the return-vs-repeat gap and the delivery/returns pattern are both flagged as not-yet-causal, confounded by vertical. I don't want to present an 8-point "returns hurt loyalty" number to the exec team if it's really just "apparel behaves differently." Let's firm that up before it goes in a deck, but it's not urgent this week.

    Questions for this week:

    1. What does a stalled cart actually contain, and does it differ from a fast-converting one? I'm thinking about basket size, price point, discount/coupon presence — anything that hints at why someone hesitates for hours or days instead of minutes.
    2. Is the cart bleed getting better, worse, or flat over the past year? If it's been stable at ~70% for two years, that's a structural product problem; if it's worsening recently, something changed (a checkout step, a fee, a release) that we should find and reverse.
    3. Of the carts that eventually do convert after sitting a while, is there a nudge already happening (a reminder, a return visit, a discount) that we could learn from and do more deliberately? I want to know if recovery is already happening organically before we invest in prompting it.
    4. On the subscription merchants' tracking gap — is this just a blind spot in how we instrument recurring orders, or is it telling us something about how those shoppers actually behave (e.g., they never browse again after the first signup)? A quick gut-check is enough this week; no need for a deep investigation yet.

    Keep the returns/delivery vertical-control work and the causal retention question on the list for whenever a slot frees up, but the cart story is what I want to walk into the roadmap review with real conviction on.

    Thanks, Emeka — strong week.

    Jonas

  3. Emeka Obi plans the night

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

    Reading last night's reports — this is the last night before the memo, so I'm using these 3 slots to close the most important open questions rather than open new ones.

    Report 1 (email nudge, guest vs. logged-in) clarifies a lot: guest carts (null user_id) converted at exactly 0.0% (0 of 7,540) — once I think about it, this is almost certainly structural: orders.user_id is not-null in the schema, so a cart can only ever reach status='converted' once it's tied to a logged-in user. That reframes the story — the real "cliff" isn't the 1-7 day window per se, it's whether the shopper ever logs in/creates an account at all. Among carts that are tied to a logged-in user, received_email converts at 56.0% vs. 20.9% with no email — still a big, consistent gap (and the math cross-checks cleanly against last week's blended 8.1% no-email figure), but I want to know what kind of email that actually is before calling it a proven "nudge effect," since it could just be that more-engaged customers both get more email and convert more.

    Report 2 (Cragsley daily, Nov 17-Dec 1) does show Nov 24-25 (36.7%, 31.25%) a bit below the Nov 17-23 average (~41%), with recovery starting Nov 26 as Black Friday demand kicks in — suggestive of a real but small dip, but daily samples are only ~35-55 carts, too noisy to trust without a longer weekday-matched baseline.

    Report 3 (single vs. multi-item, by tenant) holds up across all 6 tenants (gap 16-34 points) — good, this isn't a one-merchant artifact. But given report 1's guest-conversion finding, I now need to check whether "single-item carts convert worse" is really just another face of "guest carts convert worse" (if guests disproportionately add just one item), since that would change the headline recommendation from "nudge small-basket shoppers" to "get people to log in."

    Tonight's 3 requests: (1) the guest-vs-logged-in confound check on the item-count finding — the most important one, since it could change the Q1 headline; (2) what template/channel is actually behind the "received_email" recovery effect, to judge whether it's a deliberate cart-recovery mechanism or just general engagement; (3) a weekday-matched baseline for Cragsley (more Mondays/Tuesdays) to get a more statistically grounded read on whether Nov 24-25 was really unusual.

    Weekday-matched cart conversion baseline for Cragsley Outfitters, Sep 29 – Nov 25 2025
    Question
    Were Nov 24-25 (the start of the reminder-email outage) unusually low for their day of week, or within normal week-to-week variation?
    One row per
    calendar date (Mondays and Tuesdays only), Cragsley Outfitters
    Columns
    • date
    • day of week
    • carts created
    • overall conversion pct
  4. Omar writes the SQL

    The engineer · 2 dry runs on the empty schema, then the submission

    Dry run 1 · STATUS: REJECTED
    select
      date(c.created_at) as cart_date,
      to_char(c.created_at, 'Day') as day_of_week,
      count(*) as carts_created,
      round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pct
    from carts c
    join tenants t on t.id = c.tenant_id
    where t.name = 'Cragsley Outfitters'
      and date(c.created_at) between date '2025-09-29' and date '2025-11-25'
      and extract(isodow from c.created_at) in (1, 2)
    group by date(c.created_at), to_char(c.created_at, 'Day')
    order by cart_date asc
    Dry run 2 · 3 changes from the dry run before · STATUS: COMPILES (dry run on the empty schema, no data read)
    select  date(c.created_at) as cart_date,  to_char(c.created_at, 'Day') as day_of_week,  cd.calendar_date as date,  cd.day_name as day_of_week,  count(*) as carts_created,  round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pctfrom carts cjoin tenants t on t.id = c.tenant_idjoin calendar_days cd on cd.calendar_date = date(c.created_at)where t.name = 'Cragsley Outfitters'  and date(c.created_at) between date '2025-09-29' and date '2025-11-25'  and extract(isodow from c.created_at) in (1, 2)group by date(c.created_at), to_char(c.created_at, 'Day')order by cart_date asc  and cd.calendar_date between date '2025-09-29' and date '2025-11-25'  and cd.iso_day_of_week in (1, 2)group by cd.calendar_date, cd.day_nameorder by cd.calendar_date asc

    “This compiles and returns 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. The report covers all 18 Monday/Tuesday dates from 2025-09-29 through 2025-11-25 for Cragsley Outfitters, with carts created and overall conversion pct per date, ordered ascending — giving Emeka 8 prior weeks of same-weekday history to compare against Nov 24-25.”

  5. The report comes back overnight

    As Emeka Obi saw it, from the small dataset the agents worked on

    date       | day_of_week | carts_created | overall_conversion_pct
    -----------+-------------+---------------+-----------------------
    2025-09-29 | Monday      |            27 |                   29.6
    2025-09-30 | Tuesday     |            18 |                   33.3
    2025-10-06 | Monday      |            28 |                   28.6
    2025-10-07 | Tuesday     |            35 |                   34.3
    2025-10-13 | Monday      |            42 |                   45.2
    2025-10-14 | Tuesday     |            26 |                   42.3
    2025-10-20 | Monday      |            23 |                   39.1
    2025-10-21 | Tuesday     |            28 |                   21.4
    2025-10-27 | Monday      |            29 |                   34.5
    2025-10-28 | Tuesday     |            28 |                   39.3
    2025-11-03 | Monday      |            38 |                   31.6
    2025-11-04 | Tuesday     |            41 |                   29.3
    2025-11-10 | Monday      |            32 |                   43.8
    2025-11-11 | Tuesday     |            42 |                   28.6
    2025-11-17 | Monday      |            51 |                   45.1
    2025-11-18 | Tuesday     |            38 |                   52.6
    2025-11-24 | Monday      |            49 |                   36.7
    2025-11-25 | Tuesday     |            48 |                   31.3
    (18 rows)
  6. What came of it

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

    Emeka Obi's memo to Jonas Feld at the end of the week:

    • 4. Consistent with #3, the Nov 24 reminder-email bug doesn't show up in the data. A weekday-matched baseline (8 prior Mondays/Tuesdays for Cragsley) shows Nov 24 (36.7%) and Nov 25 (31.3%) sit comfortably inside normal week-to-week swings (21.4%–52.6%). Report: "Weekday-matched cart conversion baseline." Combined with last week's flat Jan–Oct monthly trend, I'm now fairly confident: the cart bleed is a stable, structural pattern, not a recent regression — which matches your framing of "a structural product problem" rather than something that broke.

    It builds on:

  7. It becomes benchmark query q298

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

    • spellingdate cast
    • numericsdocs/NUMERICS.md: rounding removed; results keep full precision
    • 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
    select  cd.calendar_date as date,  cd.day_name as day_of_week,  count(*) as carts_created,  round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pct  100.0 * count(*) filter (where c.status = 'converted') / count(*) as overall_conversion_pctfrom carts cjoin tenants t on t.id = c.tenant_idjoin calendar_days cd on cd.calendar_date = date(c.created_at)join calendar_days cd on cd.calendar_date = CAST(c.created_at AS DATE)where t.name = 'Cragsley Outfitters'  and cd.calendar_date between date '2025-09-29' and date '2025-11-25'  and cd.iso_day_of_week in (1, 2)group by cd.calendar_date, cd.day_nameorder by cd.calendar_date ascorder by cd.calendar_date asc NULLS LAST
    select
      cd.calendar_date as date,
      cd.day_name as day_of_week,
      count(*) as carts_created,
      100.0 * count(*) filter (where c.status = 'converted') / count(*) as overall_conversion_pct
    from carts c
    join tenants t on t.id = c.tenant_id
    join calendar_days cd on cd.calendar_date = CAST(c.created_at AS DATE)
    where t.name = 'Cragsley Outfitters'
      and cd.calendar_date between date '2025-09-29' and date '2025-11-25'
      and cd.iso_day_of_week in (1, 2)
    group by cd.calendar_date, cd.day_name
    order by cd.calendar_date asc NULLS LAST
    1 ms10 ms100 ms1 sHyper9.2 msDuckDB11.7 msGizmoSQL13.0 msclickhouse_brew130 msFirebolt54.0 msDataFusion61.5 msClickHouse177 ms
  8. 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

    Omar's whole session, 9 turns
    • The request, as Omar received it
      Report request from Emeka Obi (analyst for the VP Product):
      
      Title: Weekday-matched cart conversion baseline for Cragsley Outfitters, Sep 29 – Nov 25 2025
      Question: Were Nov 24-25 (the start of the reminder-email outage) unusually low for their day of week, or within normal week-to-week variation?
      Grain: one row per calendar date (Mondays and Tuesdays only), Cragsley Outfitters
      Columns:
      - date
      - day of week
      - carts created
      - overall conversion pct
      Details: Tenant: Cragsley Outfitters. Population: carts with created_at on every Monday and Tuesday from 2025-09-29 through 2025-11-25 inclusive (9 Mondays, 9 Tuesdays = 18 rows), using the same overall_conversion_pct definition (share of that day's carts with status='converted', any time) as prior Cragsley reports. This extends the existing Nov 17-Dec 1 daily report backward with same-weekday history so Nov 24 (Monday) and Nov 25 (Tuesday) can be compared against 8 prior weeks of the same weekdays rather than just the single preceding week. Order rows by date ascending.
      
      Check your query with the warehouse's dry_run tool, then hand it in with submit.
    • Omar calls dry_run
      select
        date(c.created_at) as cart_date,
        to_char(c.created_at, 'Day') as day_of_week,
        count(*) as carts_created,
        round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pct
      from carts c
      join tenants t on t.id = c.tenant_id
      where t.name = 'Cragsley Outfitters'
        and date(c.created_at) between date '2025-09-29' and date '2025-11-25'
        and extract(isodow from c.created_at) in (1, 2)
      group by date(c.created_at), to_char(c.created_at, 'Day')
      order by cart_date asc
    • The warehouse answers
      STATUS: REJECTED
        - does not compile: Catalog Error: Scalar Function with name to_char does not exist!
    • Omar calls dry_run
      select
        cd.calendar_date as date,
        cd.day_name as day_of_week,
        count(*) as carts_created,
        round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pct
      from carts c
      join tenants t on t.id = c.tenant_id
      join calendar_days cd on cd.calendar_date = date(c.created_at)
      where t.name = 'Cragsley Outfitters'
        and cd.calendar_date between date '2025-09-29' and date '2025-11-25'
        and cd.iso_day_of_week in (1, 2)
      group by cd.calendar_date, cd.day_name
      order by cd.calendar_date asc
    • The warehouse answers
      STATUS: COMPILES (dry run on the empty schema, no data read)
      COLUMNS: date, day_of_week, carts_created, overall_conversion_pct
    • OmarThis compiles and returns the expected columns. Submitting.
    • Omar calls submit
      select
        cd.calendar_date as date,
        cd.day_name as day_of_week,
        count(*) as carts_created,
        round(100.0 * count(*) filter (where c.status = 'converted') / count(*), 1) as overall_conversion_pct
      from carts c
      join tenants t on t.id = c.tenant_id
      join calendar_days cd on cd.calendar_date = date(c.created_at)
      where t.name = 'Cragsley Outfitters'
        and cd.calendar_date between date '2025-09-29' and date '2025-11-25'
        and cd.iso_day_of_week in (1, 2)
      group by cd.calendar_date, cd.day_name
      order by cd.calendar_date asc
    • The warehouse answers
      Submitted to tonight's batch. Your work on this request is done.
    • OmarSubmitted. The report covers all 18 Monday/Tuesday dates from 2025-09-29 through 2025-11-25 for Cragsley Outfitters, with carts created and overall conversion pct per date, ordered ascending — giving Emeka 8 prior weeks of same-weekday history to compare against Nov 24-25.