|
3 | 3 | ) |
4 | 4 | }} |
5 | 5 |
|
6 | | --- Here we give a list of all pairs of encounters |
7 | | --- that have some date overlap. |
8 | 6 |
|
| 7 | +with encounter_enhanced as ( |
| 8 | + select |
| 9 | + * |
| 10 | + , COALESCE( |
| 11 | + case |
| 12 | + when {{ dbt.datediff("discharge_date", "admit_date","day") }} >= 1 |
| 13 | + then {{ dbt.datediff("discharge_date", "admit_date","day") }} |
| 14 | + end |
| 15 | + , 1 |
| 16 | + ) as actual_length_of_stay |
9 | 17 |
|
10 | | -with encounters_with_row_num as ( |
11 | | -select |
12 | | - encounter_id |
13 | | - , person_id |
14 | | - , admit_date |
15 | | - , discharge_date |
16 | | - , row_number() over ( |
17 | | - partition by person_id |
18 | | -order by encounter_id |
19 | | - ) as row_num |
20 | | -from {{ ref('readmissions__encounter') }} |
21 | | -) |
| 18 | + -- Source type priority (lower number = higher priority) |
| 19 | + , case |
| 20 | + when UPPER(TRIM(COALESCE(encounter_source_type, ''))) = 'CLAIM' then 1 |
| 21 | + else 2 |
| 22 | + end as source_type_priority |
22 | 23 |
|
| 24 | + -- Data completeness score (count of complete fields, higher = better) |
| 25 | + , (case when discharge_disposition_code is not null |
| 26 | + and TRIM(discharge_disposition_code) != '' |
| 27 | + and TRIM(discharge_disposition_code) != '00' then 1 else 0 end) + |
| 28 | + (case when drg_code_type is not null |
| 29 | + and TRIM(drg_code_type) != '' then 1 else 0 end) + |
| 30 | + (case when drg_code is not null |
| 31 | + and TRIM(drg_code) != '' |
| 32 | + and TRIM(drg_code) not in ('998', '999') then 1 else 0 end) + |
| 33 | + (case when paid_amount is not null then 1 else 0 end) + |
| 34 | + (case when primary_diagnosis_code is not null |
| 35 | + and TRIM(primary_diagnosis_code) != '' then 1 else 0 end) as completeness_score |
| 36 | + from {{ ref('readmissions__encounter') }} |
| 37 | +) |
23 | 38 |
|
24 | | -, cartesian as ( |
25 | | -select |
26 | | - aa.encounter_id as encounter_id_a |
27 | | - , bb.encounter_id as encounter_id_b |
28 | | - , aa.person_id |
29 | | - , aa.admit_date as ai |
30 | | - , aa.discharge_date as af |
31 | | - , bb.admit_date as bi |
32 | | - , bb.discharge_date as bf |
33 | | - , case |
34 | | - when (aa.admit_date between bb.admit_date and bb.discharge_date) or (aa.discharge_date between bb.admit_date and bb.discharge_date) or |
35 | | - (bb.admit_date between aa.admit_date and aa.discharge_date) or (bb.discharge_date between aa.admit_date and aa.discharge_date) |
36 | | - then 1 |
37 | | - else 0 |
38 | | - end as overlap |
39 | | - from encounters_with_row_num as aa |
40 | | - left outer join encounters_with_row_num as bb |
41 | | - on aa.person_id = bb.person_id and aa.row_num < bb.row_num |
| 39 | +-- Identify all encounters that have overlapping dates with other encounters for the same person |
| 40 | +, overlapping_encounters as ( |
| 41 | + select distinct |
| 42 | + e1.encounter_id |
| 43 | + , e1.person_id |
| 44 | + , e1.admit_date |
| 45 | + , e1.discharge_date |
| 46 | + from encounter_enhanced as e1 |
| 47 | + where exists ( |
| 48 | + select 1 |
| 49 | + from encounter_enhanced as e2 |
| 50 | + where e1.person_id = e2.person_id |
| 51 | + and e1.encounter_id != e2.encounter_id |
| 52 | + and e1.admit_date <= e2.discharge_date |
| 53 | + and e1.discharge_date >= e2.admit_date |
| 54 | + ) |
42 | 55 | ) |
43 | 56 |
|
| 57 | +-- Create overlap groups by assigning a group identifier |
| 58 | +, overlap_groups as ( |
| 59 | + select distinct /* distinct here to prevent fan out for >2 overlapping encounters. */ |
| 60 | + e1.encounter_id |
| 61 | + , e1.person_id |
| 62 | + , MIN(e2.encounter_id) over ( |
| 63 | + partition by e1.person_id, e1.encounter_id |
| 64 | + ) as overlap_group_id |
| 65 | + from overlapping_encounters as e1 |
| 66 | + inner join overlapping_encounters as e2 |
| 67 | + on e1.person_id = e2.person_id |
| 68 | + and e1.admit_date <= e2.discharge_date |
| 69 | + and e1.discharge_date >= e2.admit_date |
| 70 | +) |
44 | 71 |
|
45 | | -, overlapping_pairs as ( |
46 | | - select |
47 | | - person_id |
48 | | - , encounter_id_a |
49 | | - , encounter_id_b |
50 | | - from cartesian |
51 | | - where overlap = 1 |
| 72 | +-- Rank encounters within each overlap group |
| 73 | +, encounter_rankings as ( |
| 74 | + select |
| 75 | + e.* |
| 76 | + , COALESCE(og.overlap_group_id, e.encounter_id) as overlap_group_id |
| 77 | + , case when og.encounter_id is not null then 1 else 0 end as has_overlaps |
| 78 | + , ROW_NUMBER() over ( |
| 79 | + partition by e.person_id, COALESCE(og.overlap_group_id, e.encounter_id) |
| 80 | + order by |
| 81 | + e.source_type_priority asc -- prefer 'claim' source type |
| 82 | + , e.actual_length_of_stay desc -- prefer longer date spans |
| 83 | + , e.completeness_score desc -- prefer more complete data |
| 84 | + , e.encounter_id asc -- Consistent tie-breaker |
| 85 | + ) as encounter_rank_in_group |
| 86 | + from encounter_enhanced as e |
| 87 | + left outer join overlap_groups as og |
| 88 | + on e.encounter_id = og.encounter_id |
| 89 | + and e.person_id = og.person_id |
52 | 90 | ) |
53 | 91 |
|
54 | 92 |
|
| 93 | +select |
| 94 | + encounter_id |
| 95 | + , person_id |
| 96 | + , admit_date |
| 97 | + , discharge_date |
| 98 | + , actual_length_of_stay |
| 99 | + , source_type_priority |
| 100 | + , completeness_score |
| 101 | + , overlap_group_id |
| 102 | + , has_overlaps |
| 103 | + , encounter_rank_in_group |
| 104 | + , case |
| 105 | + when encounter_rank_in_group = 1 then 1 |
| 106 | + else 0 |
| 107 | + end as is_best_encounter |
| 108 | + |
| 109 | + , case |
| 110 | + when encounter_rank_in_group = 1 and has_overlaps = 1 then 'Selected as best among overlapping encounters' |
| 111 | + when encounter_rank_in_group = 1 and has_overlaps = 0 then 'No overlapping encounters' |
| 112 | + else 'Not selected - better encounter exists' |
| 113 | + end as selection_reason |
55 | 114 |
|
56 | | -select *, '{{ var('tuva_last_run') }}' as tuva_last_run |
57 | | -from overlapping_pairs |
| 115 | +from encounter_rankings |
0 commit comments