You can use this query targeting the UAT data to generate the above table.
WITH patients_without_episodes AS (
SELECT
p."id" as patient_id,
p."is_dummy_patient",
p."registered_practice_id",
p."record_owner_organisation_code",
p."birth_year",
p."nhs_number_hash"
FROM "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."PATIENT" p
LEFT JOIN "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."EPISODE_OF_CARE" eoc
ON p."id" = eoc."patient_id"
WHERE eoc."patient_id" IS NULL
),
total_patients AS (
SELECT COUNT(*) as total_count
FROM "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."PATIENT"
WHERE NOT "is_dummy_patient"
)
SELECT
'Impact Summary' as section_type,
'Total Patients' as metric,
tp.total_count as value,
100.0 as percentage,
'All real patients in system' as description
FROM total_patients tp
UNION ALL
SELECT
'Impact Summary',
'Patients Missing Episode of Care Records',
COUNT(*),
ROUND(COUNT(*)::FLOAT / (SELECT total_count FROM total_patients) * 100, 2),
'Real patients with no registration history'
FROM patients_without_episodes
WHERE NOT "is_dummy_patient"
UNION ALL
SELECT
'Impact Summary',
'Have Current Practice Registration (registered_practice_id)',
COUNT(CASE WHEN "registered_practice_id" IS NOT NULL THEN 1 END),
ROUND(COUNT(CASE WHEN "registered_practice_id" IS NOT NULL THEN 1 END)::FLOAT / NULLIF(COUNT(*), 0) * 100, 1),
'Of affected patients with current GP practice assignment'
FROM patients_without_episodes
WHERE NOT "is_dummy_patient"
UNION ALL
SELECT
'Impact Summary',
'Have NHS Number Hash',
COUNT(CASE WHEN "nhs_number_hash" IS NOT NULL THEN 1 END),
ROUND(COUNT(CASE WHEN "nhs_number_hash" IS NOT NULL THEN 1 END)::FLOAT / NULLIF(COUNT(*), 0) * 100, 1),
'Of affected patients with valid NHS numbers'
FROM patients_without_episodes
WHERE NOT "is_dummy_patient"
UNION ALL
SELECT
'Impact Summary',
'Completely Orphaned (no registered_practice_id)',
COUNT(CASE WHEN "registered_practice_id" IS NULL THEN 1 END),
ROUND(COUNT(CASE WHEN "registered_practice_id" IS NULL THEN 1 END)::FLOAT / NULLIF(COUNT(*), 0) * 100, 1),
'No current GP practice AND no episode records'
FROM patients_without_episodes
WHERE NOT "is_dummy_patient"
UNION ALL
SELECT
'Validation Checks',
'Patient Type Confirmation',
COUNT(CASE WHEN "is_dummy_patient" = FALSE THEN 1 END),
0.0,
'Confirmed real patients (is_dummy_patient = FALSE)'
FROM patients_without_episodes
UNION ALL
SELECT
'Validation Checks',
'Dummy Patients in Affected Set',
COUNT(CASE WHEN "is_dummy_patient" = TRUE THEN 1 END),
0.0,
'Should be 0 - confirms this affects real data'
FROM patients_without_episodes
UNION ALL
SELECT
'Validation Checks',
'NULL Dummy Flags',
COUNT(CASE WHEN "is_dummy_patient" IS NULL THEN 1 END),
0.0,
'Patients with undefined dummy status'
FROM patients_without_episodes
UNION ALL
SELECT
'Data Quality Indicators',
'Episode of Care Coverage',
(SELECT COUNT(*) FROM "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."PATIENT" p
JOIN "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."EPISODE_OF_CARE" eoc ON p."id" = eoc."patient_id"
WHERE NOT p."is_dummy_patient"),
ROUND((SELECT COUNT(*) FROM "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."PATIENT" p
JOIN "Data_Store_OLIDS_UAT"."OLIDS_MASKED"."EPISODE_OF_CARE" eoc ON p."id" = eoc."patient_id"
WHERE NOT p."is_dummy_patient")::FLOAT /
(SELECT total_count FROM total_patients) * 100, 2),
'Real patients WITH episode of care records'
UNION ALL
SELECT
'Data Quality Indicators',
'Missing Registration History',
COUNT(*),
ROUND(COUNT(*)::FLOAT / (SELECT total_count FROM total_patients) * 100, 2),
'Real patients WITHOUT any registration history'
FROM patients_without_episodes
WHERE NOT "is_dummy_patient"
ORDER BY
CASE section_type
WHEN 'Impact Summary' THEN 1
WHEN 'Validation Checks' THEN 2
WHEN 'Data Quality Indicators' THEN 3
END,
metric;
Problem Summary
Impact
Evidence
(patient.registered_practice_id)
Query:
You can use this query targeting the UAT data to generate the above table.