-
Notifications
You must be signed in to change notification settings - Fork 0
/
buildConditionEras.sql
114 lines (111 loc) · 2.74 KB
/
buildConditionEras.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
TRUNCATE TABLE condition_era;
WITH cte_source_periods (
row_num,
person_id,
start_date,
end_date,
concept_id
)
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 ROW_NUMBER() OVER (
ORDER BY person_id
) AS row_num,
person_id AS person_id,
condition_start_date AS start_date,
COALESCE(condition_end_date, condition_start_date) AS end_date,
condition_concept_id AS concept_id
FROM condition_occurrence source_table
WHERE condition_concept_id != 0
),
cte_end_dates (
person_id,
concept_id,
end_date
)
AS -- the magic
(
SELECT person_id,
concept_id,
DATEADD(DAY, - 30, event_date) AS end_date -- unpad the end date
FROM (
SELECT person_id,
concept_id,
event_date,
event_type,
MAX(start_ordinal) OVER (
PARTITION BY person_id,
concept_id ORDER BY event_date,
event_type rows unbounded preceding
) AS start_ordinal, -- this pulls the current start down from the prior rows so that the nulls from the end dates will contain a value we can compare with
ROW_NUMBER() OVER (
PARTITION BY person_id,
concept_id ORDER BY event_date,
event_type
) AS overall_ord -- this re-numbers the inner union so all rows are numbered ordered by the event date
FROM (
-- select the start dates, assigning a row number to each
SELECT person_id,
concept_id,
start_date AS event_date,
- 1 AS event_type,
ROW_NUMBER() OVER (
PARTITION BY person_id,
concept_id ORDER BY start_date
) AS start_ordinal
FROM cte_source_periods
UNION ALL
-- pad the end dates by 30 to allow a grace period for overlapping ranges.
SELECT person_id,
concept_id,
DATEADD(DAY, 30, end_date),
1 AS event_type,
NULL
FROM cte_source_periods
) rawdata
) e
WHERE (2 * e.start_ordinal) - e.overall_ord = 0
),
cte_ends (
person_id,
concept_id,
start_date,
end_date
)
AS (
SELECT d.person_id,
d.concept_id,
d.start_date,
MIN(e.end_date) AS era_end_date
FROM cte_source_periods d
INNER JOIN cte_end_dates e
ON d.person_id = e.person_id
AND d.concept_id = e.concept_id
AND e.end_date >= d.start_date
GROUP BY d.row_num,
d.person_id,
d.concept_id,
d.start_date
)
INSERT INTO condition_era (
condition_era_id,
person_id,
condition_concept_id,
condition_era_start_date,
condition_occurrence_count,
condition_era_end_date
)
SELECT ROW_NUMBER() OVER (
ORDER BY person_id
) AS condition_era_id,
person_id AS person_id,
concept_id AS condition_concept_id,
MIN(start_date) AS condition_era_start_date,
COUNT(*) AS condition_occurrence_count,
end_date AS condition_era_end_date
FROM cte_ends
GROUP BY person_id,
concept_id,
end_date
ORDER BY person_id,
concept_id;