Ok, so my quck-and-dirty answer (which you’ll have to translate the below to your own query):
Gap days is basically the duration of the calculated era - durations of individual exposures found in the era.group. So, the gap days can be caluclated by adding this to your final select:
datediff(d, min(drug_exposure_start_date), drug_exposure_end_date) - SUM(days_exposed)
The trick is that we need to calculate the days_exposed from the original set of records from cteDrugTarget, so change it:
select DRUG_EXPOSURE_ID, PERSON_ID, DRUG_CONCEPT_ID, DRUG_EXPOSURE_START_DATE,
COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day,DAYS_SUPPLY,DRUG_EXPOSURE_START_DATE), DATEADD(day,1,DRUG_EXPOSURE_START_DATE)) as DRUG_EXPOSURE_END_DATE,
DATEDIFF(day, DRUG_EXPOSURE_START_DATE, COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day,DAYS_SUPPLY,DRUG_EXPOSURE_START_DATE), DATEADD(day,1,DRUG_EXPOSURE_START_DATE)) as days_exposed
FROM @TARGET_CDMV5_SCHEMA.DRUG_EXPOSURE de
join @TARGET_CDMV5_SCHEMA.CONCEPT_ANCESTOR ca on ca.DESCENDANT_CONCEPT_ID = de.DRUG_CONCEPT_ID
join @TARGET_CDMV5_SCHEMA.CONCEPT c on ca.ANCESTOR_CONCEPT_ID = c.CONCEPT_ID
where c.VOCABULARY_ID = 'RxNorm'
and c.CONCEPT_CLASS_ID = 'Ingredient'
You need to include the ‘days_exposed’ in the cteEnds
so that you can access it in the final select.
Below is the complete solution:
with cteDrugTarget (DRUG_EXPOSURE_ID, PERSON_ID, DRUG_CONCEPT_ID, DRUG_EXPOSURE_START_DATE, DRUG_EXPOSURE_END_DATE) as
(
-- Normalize DRUG_EXPOSURE_END_DATE to either the existing drug exposure end date, or add days supply, or add 1 day to the start date
select DRUG_EXPOSURE_ID, PERSON_ID, DRUG_CONCEPT_ID, DRUG_EXPOSURE_START_DATE,
COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day,DAYS_SUPPLY,DRUG_EXPOSURE_START_DATE), DATEADD(day,1,DRUG_EXPOSURE_START_DATE)) as DRUG_EXPOSURE_END_DATE,
DATEDIFF(day, DRUG_EXPOSURE_START_DATE, COALESCE(DRUG_EXPOSURE_END_DATE, DATEADD(day,DAYS_SUPPLY,DRUG_EXPOSURE_START_DATE), DATEADD(day,1,DRUG_EXPOSURE_START_DATE)) as DAYS_EXPOSED
FROM @TARGET_CDMV5_SCHEMA.DRUG_EXPOSURE de
join @TARGET_CDMV5_SCHEMA.CONCEPT_ANCESTOR ca on ca.DESCENDANT_CONCEPT_ID = de.DRUG_CONCEPT_ID
join @TARGET_CDMV5_SCHEMA.CONCEPT c on ca.ANCESTOR_CONCEPT_ID = c.CONCEPT_ID
where c.VOCABULARY_ID = 'RxNorm'
and c.CONCEPT_CLASS_ID = 'Ingredient'
),
cteEndDates (person_id, drug_concept_id, end_date) AS
(
SELECT
person_id,
drug_concept_id,
DATEADD(day,-30, event_date) as end_date
FROM
(
SELECT person_id,
drug_concept_id,
event_date,
SUM(event_type) OVER (PARTITION BY person_id, drug_concept_id ORDER BY event_date ROWS UNBOUNDED PRECEDING) AS interval_status
FROM
(
SELECT
person_id,
drug_concept_id,
drug_exposure_start_date AS event_date,
-1 AS event_type
FROM cteDrugTarget
UNION ALL
SELECT
person_id,
drug_concept_id,
DATEADD(day, 30, drug_exposure_end_date) AS event_date,
1 AS event_type
FROM cteDrugTarget
) RAWDATA
) e
WHERE interval_status = 0
),
cteEnds (person_id, drug_exposure_id, drug_concept_id, drug_exposure_start_date, drug_exposure_end_date, days_exposed) AS
(
SELECT de.person_id,
de.drug_exposure_id,
de.drug_concept_id,
de.drug_exposure_start_date as start_date,
MIN(e.end_date) AS drug_exposure_end_date,
de.days_exposed
FROM cteDrugTarget de
INNER JOIN cteEndDates e ON de.person_id = e.person_id
AND de.drug_concept_id = e.drug_concept_id
AND e.end_date >= de.drug_exposure_start_date
GROUP BY de.person_id,
de.drug_exposure_id,
de.drug_concept_id,
de.drug_exposure_start_date
de.days_exposed
)
select top 10 person_id, drug_concept_id, min(drug_exposure_start_date) as drug_exposure_start_date, drug_exposure_end_date,
count(*) as drug_exposure_connt,
datediff(day, min(drug_exposure_start_date), drug_exposure_end_date) - SUM(days_exposed) as gap_days
from cteEnds
group by person_id, drug_concept_id, drug_exposure_end_date
;
I’m unable to test this on my local env this time, so you may experience errors.
Also note: gap_days could be a negative value when you have a lot of drug_exposure overlaps (causing the sum of exposure days within an era to exceed the actual duration of the era). This is referred to as ‘stockpiling’ and it’s not something that is handled in this logic.