Queries · q400 · Support Operations Manager · week 2, night 1
“What share of 2025 tickets carry no topic tag at all, and do untagged tickets differ from tagged ones enough to change the topic/breach story from last week?”
Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told
Week 1; shared with Daniel Achterberg, VP Customer Experience
Review how the helpdesk runs: queues and agent groups, use of macros and knowledge articles, SLA targets and breaches, and what makes tickets slow.
The manager, at the start of week 2
Subject: Re: Helpdesk Operating Review — great start, here's where to push next
Ben,
This is exactly the kind of baseline I wanted — and the speed-to-CSAT finding alone is worth putting in front of Daniel as-is. A few things stood out that I want sharpened before we present or act on them.
What surprised me / needs explaining:
Questions for next week, in priority order:
Thanks — this is shaping up well. Let's make next week about turning the Marrowby & Vane / Studio Vrij question into something actionable.
Mia
The analyst · week 2, night 1, request 3 of 3
Mia's top priority is turning the Marrowby & Vane / Studio Vrij finding into "hire" vs "something else" — so tonight's first slot benchmarks their staffing ratio (tickets per agent) against complexity signals (messages per ticket, priority mix) alongside Cragsley and a few other top merchants as controls. I already have a hint this isn't pure under-staffing: last week's data showed Cragsley's Customer Care group runs a similar or higher tickets-per-agent ratio than Studio Vrij's yet breaches far less, which points toward ticket difficulty rather than headcount — tonight's report will test that properly with complexity proxies instead of my eyeballing two reports side by side. Second, since there's no usage-event ledger behind macros.usage_count, the only way to sanity-check it is to see if the audit trail (change_history/audit_log) corroborates the counter for our top macros — if the audit trail barely covers the counter's growth, that's itself the finding (and echoes the audit-gap theme several other teams hit this week), and I'll say so plainly rather than repeat the unreliable number. Third, a cheap but necessary check before any topic/tag training conversation: how much of 2025 ticket volume carries no tag at all, and whether untagged tickets look different enough to change the story. KB-deflection (Mia's Q4) waits for night 2 since these three fill tonight's slots and matter more.
The engineer · 1 dry run on the empty schema, then the submission
WITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' ), counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status ), grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3 ), resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(EXTRACT(EPOCH FROM (t4.resolved_at - t4.created_at)) / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status ), resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status ), first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status ) SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, ROUND(100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0), 1) AS pct_of_total_tickets, ROUND(COALESCE(t11.avg_resolution_minutes, 0), 0) AS avg_resolution_minutes, ROUND(100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS resolution_breach_rate, ROUND(100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS first_response_breach_rate FROM counts t9 CROSS JOIN grand_total t10 LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_status LEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_status LEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_status ORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END, t9.coverage_status
“Query compiles cleanly with the expected columns. Submitting.”
“The report has been submitted. Summary of what it delivers:
- Grain: one row per coverage_status ('Tagged' vs 'Untagged'), 2 rows total, Tagged first.
- Measures: ticket_count, pct_of_total_tickets, avg_resolution_minutes, resolution_breach_rate, first_response_breach_rate — all for tickets created in 2025.
- Tag coverage is determined by existence of any row in ticket_tags_map per ticket.
- Resolution time is averaged only over tickets that have a resolved_at timestamp (open tickets don't contribute a duration), and breach rates are the share of each group's tickets that have at least one matching sla_breaches row (resolution or first_response kind) — noted in the submit note for the analyst.”
As Ben Carter saw it, from the small dataset the agents worked on
coverage_status | ticket_count | pct_of_total_tickets | avg_resolution_minutes | resolution_breach_rate | first_response_breach_rate ----------------+--------------+----------------------+------------------------+------------------------+--------------------------- Tagged | 2320 | 100.0 | 2687.0 | 20.3 | 37.7 (1 rows)
The memo and the queries that followed; links found by title, so inferred
It builds on:
Changed only where the benchmark needs the same result on every system
WITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01'),counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status),grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3),resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(EXTRACT(EPOCH FROM (t4.resolved_at - t4.created_at)) / 60.0) AS avg_resolution_minutes AVG({{seconds_between(t4.created_at, t4.resolved_at)}} / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status),resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status),first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status)SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, ROUND(100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0), 1) AS pct_of_total_tickets, ROUND(COALESCE(t11.avg_resolution_minutes, 0), 0) AS avg_resolution_minutes, ROUND(100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS resolution_breach_rate, ROUND(100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS first_response_breach_rate 100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0) AS pct_of_total_tickets, COALESCE(t11.avg_resolution_minutes, 0) AS avg_resolution_minutes, 100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS resolution_breach_rate, 100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS first_response_breach_rateFROM counts t9CROSS JOIN grand_total t10LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_statusLEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_statusLEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_statusORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END, t9.coverage_status CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END NULLS LAST, t9.coverage_status NULLS LAST
WITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' ), counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status ), grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3 ), resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(CAST(EXTRACT(EPOCH FROM (t4.resolved_at - t4.created_at)) AS NUMERIC(18,6)) / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status ), resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status ), first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status ) SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, 100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0) AS pct_of_total_tickets, COALESCE(t11.avg_resolution_minutes, 0) AS avg_resolution_minutes, 100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS resolution_breach_rate, 100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS first_response_breach_rate FROM counts t9 CROSS JOIN grand_total t10 LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_status LEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_status LEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_status ORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END NULLS LAST, t9.coverage_status NULLS LAST
WITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' ), counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status ), grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3 ), resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(CAST(divideDecimal(toDecimal128(dateDiff('microsecond', t4.created_at, t4.resolved_at), 0), toDecimal128(1000000, 0), 6) AS Nullable(Decimal(18, 6))) / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status ), resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status ), first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status ) SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, 100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0) AS pct_of_total_tickets, COALESCE(t11.avg_resolution_minutes, 0) AS avg_resolution_minutes, 100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS resolution_breach_rate, 100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0) AS first_response_breach_rate FROM counts t9 CROSS JOIN grand_total t10 LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_status LEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_status LEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_status ORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END NULLS LAST, t9.coverage_status NULLS LAST
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 Ben Carter (analyst for the Support Operations Manager): Title: Ticket tag coverage: tagged vs. untagged volume and speed Question: What share of 2025 tickets carry no topic tag at all, and do untagged tickets differ from tagged ones enough to change the topic/breach story from last week? Grain: one row per tag-coverage status: 'Tagged' (at least one row in ticket_tags_map) vs. 'Untagged' (no rows) Columns: - coverage_status - ticket_count (2025) - pct_of_total_tickets - avg_resolution_minutes - resolution_breach_rate - first_response_breach_rate Details: Window: tickets.created_at between 2025-01-01 and 2025-12-31. Source tables: tickets, ticket_tags_map, sla_breaches (breach_kind = 'resolution' / 'first_response'). A ticket counts as 'Tagged' if it has at least one row in ticket_tags_map, regardless of how many tags; 'Untagged' otherwise. 2 rows total. Order 'Tagged' first then 'Untagged'. Round pct and rates to 1 decimal percent, minutes to whole numbers. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runWITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' ), counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status ), grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3 ), resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(EXTRACT(EPOCH FROM (t4.resolved_at - t4.created_at)) / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status ), resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status ), first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status ) SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, ROUND(100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0), 1) AS pct_of_total_tickets, ROUND(COALESCE(t11.avg_resolution_minutes, 0), 0) AS avg_resolution_minutes, ROUND(100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS resolution_breach_rate, ROUND(100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS first_response_breach_rate FROM counts t9 CROSS JOIN grand_total t10 LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_status LEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_status LEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_status ORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END, t9.coverage_status
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: coverage_status, ticket_count, pct_of_total_tickets, avg_resolution_minutes, resolution_breach_rate, first_response_breach_rate
submitWITH ticket_base AS ( SELECT t0.id AS ticket_id, t0.created_at AS created_at, t0.resolved_at AS resolved_at, CASE WHEN EXISTS (SELECT 1 FROM ticket_tags_map t1 WHERE t1.ticket_id = t0.id) THEN 'Tagged' ELSE 'Untagged' END AS coverage_status FROM tickets t0 WHERE t0.created_at >= DATE '2025-01-01' AND t0.created_at < DATE '2026-01-01' ), counts AS ( SELECT t2.coverage_status AS coverage_status, COUNT(*) AS ticket_count FROM ticket_base t2 GROUP BY t2.coverage_status ), grand_total AS ( SELECT COUNT(*) AS total_tickets FROM ticket_base t3 ), resolution_time AS ( SELECT t4.coverage_status AS coverage_status, AVG(EXTRACT(EPOCH FROM (t4.resolved_at - t4.created_at)) / 60.0) AS avg_resolution_minutes FROM ticket_base t4 WHERE t4.resolved_at IS NOT NULL GROUP BY t4.coverage_status ), resolution_breaches AS ( SELECT t5.coverage_status AS coverage_status, COUNT(DISTINCT t6.ticket_id) AS resolution_breach_count FROM ticket_base t5 JOIN sla_breaches t6 ON t6.ticket_id = t5.ticket_id AND t6.breach_kind = 'resolution' GROUP BY t5.coverage_status ), first_response_breaches AS ( SELECT t7.coverage_status AS coverage_status, COUNT(DISTINCT t8.ticket_id) AS first_response_breach_count FROM ticket_base t7 JOIN sla_breaches t8 ON t8.ticket_id = t7.ticket_id AND t8.breach_kind = 'first_response' GROUP BY t7.coverage_status ) SELECT t9.coverage_status AS coverage_status, t9.ticket_count AS ticket_count, ROUND(100.0 * t9.ticket_count / NULLIF(t10.total_tickets, 0), 1) AS pct_of_total_tickets, ROUND(COALESCE(t11.avg_resolution_minutes, 0), 0) AS avg_resolution_minutes, ROUND(100.0 * COALESCE(t12.resolution_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS resolution_breach_rate, ROUND(100.0 * COALESCE(t13.first_response_breach_count, 0) / NULLIF(t9.ticket_count, 0), 1) AS first_response_breach_rate FROM counts t9 CROSS JOIN grand_total t10 LEFT JOIN resolution_time t11 ON t11.coverage_status = t9.coverage_status LEFT JOIN resolution_breaches t12 ON t12.coverage_status = t9.coverage_status LEFT JOIN first_response_breaches t13 ON t13.coverage_status = t9.coverage_status ORDER BY CASE WHEN t9.coverage_status = 'Tagged' THEN 0 ELSE 1 END, t9.coverage_status
Submitted to tonight's batch. Your work on this request is done.