Queries · q118 · Data Protection Officer · week 1, night 3
“Across all data subject requests (not just currently open ones), which status values leave completed_at null, and is that a systemic pattern (e.g. all rejections) or isolated to a few records?”
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: A few starting questions on privacy & data handling
Hi Priyanka,
Welcome aboard, and thank you for taking these on this week. As I get oriented, here's what I'd like to understand first. Given the slot constraints, please treat these as priorities in order — if only three fit this week, start from the top and we'll pick up the rest next week.
For now, could you scope the first request for me? I'd like to see it broken down in a way that shows me trend over the last several months, not just a single total — I want to catch whether we're improving or falling behind.
Let me know if any of these need to be split further once you see what the data looks like.
Thanks, Ines
The analyst · week 1, night 3, request 1 of 3
Report 1's big finding: all 3 of the long-overdue DSARs are status='rejected' yet have completed_at = NULL — my original monthly report (night 1) treated 'completed_at IS NULL' as the sole "still open" signal, which may be wrongly counting rejected (i.e., actually-decided) requests as backlog. Before I hand Ines a number, I need to know whether 'rejected' is a systemic gap (completed_at never set on rejections) or an isolated failure on these 3 — that reshapes the whole answer to her question 1, so it's the top priority tonight. Report 3 (retention policy inventory) was dominated by one audit_log policy repeated per tenant and got truncated at 50 of 720 rows before showing any other entity_table — I need a properly aggregated view of what policies actually exist before I can check reality against them (item 4). With only this night and one more left, I'm also opening item 5 (legal holds) tonight since it looks like a single, self-contained report I can likely close in one shot, leaving night 4 free for the retention actual-vs-policy comparison and any remaining loose ends.
The engineer · 1 dry run on the empty schema, then the submission
select status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(case when completed_at is null then date(DATE '2026-01-05') - date(received_at) end) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc, status asc
“Query compiles. Submitting.”
“Submitted. The report groups all data_subject_requests by status and reports total count, completed vs. not-completed counts, the oldest/newest received_at, and the average age (in days, relative to 2026-01-05) of the not-completed rows — which will directly show whether statuses like rejected systematically leave completed_at null or whether it's just a few stragglers.”
As Priyanka Desai saw it, from the small dataset the agents worked on
status | total_requests | completed_count | not_completed_count | oldest_received_at | newest_received_at | avg_age_days_not_completed ------------+----------------+-----------------+---------------------+----------------------------+----------------------------+--------------------------- completed | 55 | 55 | 0 | 2020-04-24 22:06:57.286184 | 2025-10-18 12:53:44.859874 | NULL rejected | 3 | 0 | 3 | 2023-05-26 18:29:11.494494 | 2025-03-21 06:44:26.231555 | 596.6666666666666 in_progress | 1 | 0 | 1 | 2025-12-29 04:46:25.41114 | 2025-12-29 04:46:25.41114 | 7.0 received | 1 | 0 | 1 | 2025-12-06 01:50:30.669686 | 2025-12-06 01:50:30.669686 | 30.0 (4 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 status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(case when completed_at is null then date(DATE '2026-01-05') - date(received_at) end) as avg_age_days_not_completed avg(cast(case when completed_at is null then {{date_diff_days(received_at, DATE '2026-01-05')}} end as numeric(18,6))) as avg_age_days_not_completedfrom data_subject_requestsgroup by statusorder by total_requests desc, status ascorder by total_requests desc NULLS FIRST, status asc NULLS LAST
select status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(cast(case when completed_at is null then DATE_DIFF('day', received_at, DATE '2026-01-05') end as numeric(18,6))) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc NULLS FIRST, status asc NULLS LAST
select status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(cast(case when completed_at is null then (CAST(DATE '2026-01-05' AS DATE) - CAST(received_at AS DATE)) end as numeric(18,6))) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc NULLS FIRST, status asc NULLS LAST
select status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(cast(case when completed_at is null then dateDiff('day', received_at, DATE '2026-01-05') end as numeric(18,6))) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc NULLS FIRST, status asc 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 Priyanka Desai (analyst for the Data Protection Officer): Title: Data subject request status audit: does completed_at reflect true closure? Question: Across all data subject requests (not just currently open ones), which status values leave completed_at null, and is that a systemic pattern (e.g. all rejections) or isolated to a few records? Grain: one row per distinct data_subject_requests.status value, across full history Columns: - status - total requests with this status - count with completed_at not null - count with completed_at null - oldest received_at in this status - newest received_at in this status - avg age in days of the completed_at-null rows (2026-01-05 minus received_at, averaged, null if none) Details: Source: data_subject_requests, no date filter (full history), platform-wide. Group by status. This is a diagnostic to check whether 'rejected' (and any other terminal-sounding status) systematically never gets a completed_at stamp, which would mean my earlier 'still open'/'overdue' counts (based on completed_at IS NULL) overstate the real backlog. Use literal date 2026-01-05 for age math. Order by total requests with this status descending. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runselect status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(case when completed_at is null then date(DATE '2026-01-05') - date(received_at) end) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc, status asc
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: status, total_requests, completed_count, not_completed_count, oldest_received_at, newest_received_at, avg_age_days_not_completed
submitselect status, count(*) as total_requests, count(completed_at) as completed_count, count(*) - count(completed_at) as not_completed_count, min(received_at) as oldest_received_at, max(received_at) as newest_received_at, avg(case when completed_at is null then date(DATE '2026-01-05') - date(received_at) end) as avg_age_days_not_completed from data_subject_requests group by status order by total_requests desc, status asc
Submitted to tonight's batch. Your work on this request is done.