Queries · q038 · VP Customer Experience · week 1, night 1
“How much does support speed vary across merchants, and who is fastest/slowest?”
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: Where I'd like to start — support & shopper experience
Hi Mateo,
Good to have you on this with me. I'm still building my map of the business, so I want to keep this week broad — I'd rather get a solid first read on a few big questions than a deep dive on one. Here's what's on my mind, roughly in priority order:
What I need these for: I'm meeting merchant success and the exec team soon and want a credible, numbers-backed view of shopper experience — not just war stories. I also want to start spotting the two or three things that, if we fixed them, would move the needle most broadly across merchants, rather than chasing individual complaints.
Given the slot constraints, let's prioritize #1 through #3 this week if we can't fit all five — those feel most urgent to me. Happy to talk through any of this before you lock in requests.
Thanks, Daniel
The analyst · week 1, night 1, request 2 of 3
Daniel's top priority is #1 (response/resolution trend, and variance by merchant), so I'm spending 2 of tonight's 3 slots there: a platform-wide monthly trend (to see direction of travel) and a per-merchant snapshot for the latest full year (to see spread across merchants, since he likes peer comparisons). The third slot starts #2 (where load comes from) with a tag-based mix comparing the last two half-years to catch any shift. I'm deliberately holding off on YoY columns inside the trend report itself since the 36-month series already shows year-over-year pattern, and saving width for the core time metrics. Returns/refunds (#3), satisfaction (#4) and reviews (#5) are next on my list for later nights.
The engineer · 1 dry run on the empty schema, then the submission
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, ROUND(CAST(t_fr.avg_first_response_hours AS numeric), 2) AS avg_first_response_hours, ROUND(CAST(t_fr.median_first_response_hours AS numeric), 2) AS median_first_response_hours, ROUND(CAST(t_res.avg_resolution_hours AS numeric), 2) AS avg_resolution_hours, ROUND(CAST(t_res.median_resolution_hours AS numeric), 2) AS median_resolution_hours, ROUND(CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric) / CAST(t_counts.tickets_created AS numeric) * 100.0, 2) AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC, t_tenant.name ASC LIMIT 50
“Submitted. The query answers the request at the requested grain (one row per tenant, 2025 tickets, ≥20-ticket threshold), with avg/median first-response and resolution hours and SLA breach rate, ordered by ticket volume descending and capped at 50 rows per house standards.”
As Mateo Ruiz saw it, from the small dataset the agents worked on
merchant_name | tickets_created | avg_first_response_hours | median_first_response_hours | avg_resolution_hours | median_resolution_hours | sla_breach_rate_pct ------------------------------+-----------------+--------------------------+-----------------------------+----------------------+-------------------------+-------------------- Cragsley Outfitters | 400 | 20.94 | 10.57 | 39.14 | 20.96 | 61.25 Marrowby & Vane | 231 | 47.24 | 11.11 | 84.93 | 20.25 | 61.47 Studio Vrij | 166 | 60.29 | 11.71 | 125.06 | 25.93 | 56.63 Brennquell Kaffee | 137 | 5.60 | 2.99 | 15.94 | 8.83 | 32.12 Grind Collective | 122 | 36.20 | 6.53 | 64.42 | 20.24 | 45.08 Petalcourt Beauty | 119 | 31.37 | 6.75 | 48.71 | 22.50 | 57.14 Kibblewick | 72 | 17.26 | 4.65 | 40.77 | 21.98 | 50.0 Spice Route Box | 71 | 7.54 | 3.08 | 16.92 | 14.07 | 33.8 Fennel & Flint | 67 | 15.35 | 3.92 | 35.20 | 14.66 | 38.81 Honeycomb Larder | 58 | 21.44 | 16.00 | 32.80 | 24.74 | 29.31 Ampfeld Elektronik | 56 | 8.71 | 4.21 | 20.06 | 13.84 | 32.14 Sourdough Club | 47 | 24.94 | 14.52 | 32.65 | 23.87 | 36.17 Ballycorran Industrial Supply | 44 | 7.90 | 5.40 | 24.50 | 20.64 | 34.09 Cinder Peak Sports Co. | 43 | 5.56 | 3.49 | 17.28 | 11.82 | 34.88 Wiesgrund Wohnen | 32 | 3.47 | 2.11 | 10.91 | 6.34 | 21.88 Linden & Loom | 29 | 4.69 | 3.46 | 13.49 | 9.71 | 37.93 Gratlinie Outdoor | 27 | 3.29 | 2.52 | 10.84 | 5.75 | 14.81 Oakhurst Tailoring | 27 | 27.17 | 19.84 | 33.33 | 31.07 | 11.11 Rue Lafayette Studio | 27 | 4.44 | 2.79 | 12.21 | 9.38 | 18.52 Coastline Interiors | 21 | 12.15 | 9.08 | 16.90 | 13.58 | 9.52 Thistlecombe | 21 | 4.92 | 4.24 | 17.93 | 14.00 | 9.52 Kayak Corner | 20 | 28.84 | 17.73 | 37.59 | 26.73 | 20.0 (22 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
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, ROUND(CAST(t_fr.avg_first_response_hours AS numeric), 2) AS avg_first_response_hours, ROUND(CAST(t_fr.median_first_response_hours AS numeric), 2) AS median_first_response_hours, ROUND(CAST(t_res.avg_resolution_hours AS numeric), 2) AS avg_resolution_hours, ROUND(CAST(t_res.median_resolution_hours AS numeric), 2) AS median_resolution_hours, ROUND(CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric) / CAST(t_counts.tickets_created AS numeric) * 100.0, 2) AS sla_breach_rate_pct t_fr.avg_first_response_hours AS avg_first_response_hours, t_fr.median_first_response_hours AS median_first_response_hours, t_res.avg_resolution_hours AS avg_resolution_hours, t_res.median_resolution_hours AS median_resolution_hours, CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric(18,6)) / CAST(t_counts.tickets_created AS numeric(18,6)) * 100.0 AS sla_breach_rate_pctFROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id) t_countsJOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_idLEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS median_first_response_hours AVG({{seconds_between(t0.created_at, t0.first_response_at)}} / 3600.0) AS avg_first_response_hours, {{percentile_cont(0.5, {{seconds_between(t0.created_at, t0.first_response_at)}} / 3600.0)}} AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id) t_fr ON t_fr.tenant_id = t_counts.tenant_idLEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS median_resolution_hours AVG({{seconds_between(t0.created_at, t0.resolved_at)}} / 3600.0) AS avg_resolution_hours, {{percentile_cont(0.5, {{seconds_between(t0.created_at, t0.resolved_at)}} / 3600.0)}} AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id) t_res ON t_res.tenant_id = t_counts.tenant_idLEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id) t_breach ON t_breach.tenant_id = t_counts.tenant_idWHERE t_counts.tickets_created >= 20ORDER BY t_counts.tickets_created DESC, t_tenant.name ASCLIMIT 50ORDER BY t_counts.tickets_created DESC NULLS FIRST, t_tenant.name ASC NULLS LAST, t_tenant.id NULLS LAST{{fetch_first(50)}}
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, t_fr.avg_first_response_hours AS avg_first_response_hours, t_fr.median_first_response_hours AS median_first_response_hours, t_res.avg_resolution_hours AS avg_resolution_hours, t_res.median_resolution_hours AS median_resolution_hours, CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric(18,6)) / CAST(t_counts.tickets_created AS numeric(18,6)) * 100.0 AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC NULLS FIRST, t_tenant.name ASC NULLS LAST, t_tenant.id NULLS LAST FETCH FIRST 50 ROWS ONLY
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, t_fr.avg_first_response_hours AS avg_first_response_hours, t_fr.median_first_response_hours AS median_first_response_hours, t_res.avg_resolution_hours AS avg_resolution_hours, t_res.median_resolution_hours AS median_resolution_hours, CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric(18,6)) / CAST(t_counts.tickets_created AS numeric(18,6)) * 100.0 AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC NULLS FIRST, t_tenant.name ASC NULLS LAST, t_tenant.id NULLS LAST LIMIT 50
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, t_fr.avg_first_response_hours AS avg_first_response_hours, t_fr.median_first_response_hours AS median_first_response_hours, t_res.avg_resolution_hours AS avg_resolution_hours, t_res.median_resolution_hours AS median_resolution_hours, CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric(18,6)) / CAST(t_counts.tickets_created AS numeric(18,6)) * 100.0 AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(CAST(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0 AS DOUBLE PRECISION)) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(CAST(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) AS NUMERIC(18,6)) / 3600.0 AS DOUBLE PRECISION)) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC NULLS FIRST, t_tenant.name ASC NULLS LAST, t_tenant.id NULLS LAST FETCH FIRST 50 ROWS ONLY
SELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, t_fr.avg_first_response_hours AS avg_first_response_hours, t_fr.median_first_response_hours AS median_first_response_hours, t_res.avg_resolution_hours AS avg_resolution_hours, t_res.median_resolution_hours AS median_resolution_hours, CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric(18,6)) / CAST(t_counts.tickets_created AS numeric(18,6)) * 100.0 AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(divideDecimal(toDecimal128(dateDiff('microsecond', t0.created_at, t0.first_response_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 3600.0) AS avg_first_response_hours, quantileExactInclusive(0.5)(toFloat64(CAST(divideDecimal(toDecimal128(dateDiff('microsecond', t0.created_at, t0.first_response_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 3600.0)) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(CAST(divideDecimal(toDecimal128(dateDiff('microsecond', t0.created_at, t0.resolved_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 3600.0) AS avg_resolution_hours, quantileExactInclusive(0.5)(toFloat64(CAST(divideDecimal(toDecimal128(dateDiff('microsecond', t0.created_at, t0.resolved_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 3600.0)) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC NULLS FIRST, t_tenant.name ASC NULLS LAST, t_tenant.id NULLS LAST FETCH FIRST 50 ROWS ONLY
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 Mateo Ruiz (analyst for the VP Customer Experience): Title: Response & resolution times by merchant, 2025 Question: How much does support speed vary across merchants, and who is fastest/slowest? Grain: one row per tenant (merchant), for tickets created in 2025 Columns: - merchant name - tickets created - avg first response hours - median first response hours - avg resolution hours - median resolution hours - SLA breach rate (%) Details: Source: tickets joined to tenants (for name) and sla_breaches (for breach rate). Filter tickets.created_at in 2025-01-01 through 2025-12-31. Same hour definitions as the monthly trend report (first_response_at - created_at, resolved_at - created_at, both in hours, only over tickets where that timestamp is not null). SLA breach rate = tenant's distinct tickets with >=1 sla_breaches row / tenant's tickets created in 2025, as a percentage. Only include tenants with at least 20 tickets created in 2025 to avoid noisy small-sample rows. Order by tickets created descending, tie-break by merchant name ascending; report will show at most 50 rows so note total tenant count meeting the threshold and how many are printed. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runSELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, ROUND(CAST(t_fr.avg_first_response_hours AS numeric), 2) AS avg_first_response_hours, ROUND(CAST(t_fr.median_first_response_hours AS numeric), 2) AS median_first_response_hours, ROUND(CAST(t_res.avg_resolution_hours AS numeric), 2) AS avg_resolution_hours, ROUND(CAST(t_res.median_resolution_hours AS numeric), 2) AS median_resolution_hours, ROUND(CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric) / CAST(t_counts.tickets_created AS numeric) * 100.0, 2) AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC, t_tenant.name ASC LIMIT 50
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: merchant_name, tickets_created, avg_first_response_hours, median_first_response_hours, avg_resolution_hours, median_resolution_hours, sla_breach_rate_pct
submitSELECT t_tenant.name AS merchant_name, t_counts.tickets_created AS tickets_created, ROUND(CAST(t_fr.avg_first_response_hours AS numeric), 2) AS avg_first_response_hours, ROUND(CAST(t_fr.median_first_response_hours AS numeric), 2) AS median_first_response_hours, ROUND(CAST(t_res.avg_resolution_hours AS numeric), 2) AS avg_resolution_hours, ROUND(CAST(t_res.median_resolution_hours AS numeric), 2) AS median_resolution_hours, ROUND(CAST(COALESCE(t_breach.breached_tickets, 0) AS numeric) / CAST(t_counts.tickets_created AS numeric) * 100.0, 2) AS sla_breach_rate_pct FROM ( SELECT t0.tenant_id AS tenant_id, COUNT(*) AS tickets_created FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_counts JOIN tenants t_tenant ON t_tenant.id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS avg_first_response_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.first_response_at - t0.created_at)) / 3600.0) AS median_first_response_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.first_response_at IS NOT NULL GROUP BY t0.tenant_id ) t_fr ON t_fr.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, AVG(EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS avg_resolution_hours, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (t0.resolved_at - t0.created_at)) / 3600.0) AS median_resolution_hours FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' AND t0.resolved_at IS NOT NULL GROUP BY t0.tenant_id ) t_res ON t_res.tenant_id = t_counts.tenant_id LEFT JOIN ( SELECT t0.tenant_id AS tenant_id, COUNT(DISTINCT t0.id) AS breached_tickets FROM tickets t0 JOIN sla_breaches t1 ON t1.ticket_id = t0.id WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' GROUP BY t0.tenant_id ) t_breach ON t_breach.tenant_id = t_counts.tenant_id WHERE t_counts.tickets_created >= 20 ORDER BY t_counts.tickets_created DESC, t_tenant.name ASC LIMIT 50
Submitted to tonight's batch. Your work on this request is done.