1- with ur_stg as
1+ WITH uo_stg1 AS
22(
3- select io .stay_id , io .charttime
4- -- we have joined each row to all rows preceding within 24 hours
5- -- we can now sum these rows to get total UO over the last 24 hours
6- -- we can use case statements to restrict it to only the last 6/12 hours
7- -- therefore we have three sums:
8- -- 1) over a 6 hour period
9- -- 2) over a 12 hour period
10- -- 3) over a 24 hour period
11- -- note that we assume data charted at charttime corresponds to 1 hour of UO
12- -- therefore we use '5' and '11' to restrict the period, rather than 6/12
13- -- this assumption may overestimate UO rate when documentation is done less than hourly
3+ SELECT ie .stay_id , uo .charttime
4+ , DATETIME_DIFF(charttime, intime, SECOND) AS seconds_since_admit
5+ , COALESCE(
6+ DATETIME_DIFF(charttime, LAG(charttime) OVER (PARTITION BY ie .stay_id ORDER BY charttime), SECOND)/ 3600 .0 ,
7+ 1
8+ ) AS hours_since_previous_row
9+ , urineoutput
10+ FROM ` physionet-data.mimiciv_icu.icustays` ie
11+ INNER JOIN ` physionet-data.mimiciv_derived.urine_output` uo
12+ ON ie .stay_id = uo .stay_id
13+ )
14+ , uo_stg2 as
15+ (
16+ select stay_id, charttime
17+ , hours_since_previous_row
18+ , urineoutput
19+ -- Use the RANGE partition to limit the summation to the last X hours.
20+ -- RANGE operates using numeric, so we convert the charttime into seconds
21+ -- since admission, and then filter to X seconds prior to the current row.
22+ -- where X can be 21600 (6 hours), 43200 (12 hours), or 86400 (24 hours).
23+ , SUM (urineoutput) OVER
24+ (
25+ PARTITION BY stay_id
26+ ORDER BY seconds_since_admit
27+ RANGE BETWEEN 21600 PRECEDING AND CURRENT ROW
28+ ) AS urineoutput_6hr
29+
30+ , SUM (urineoutput) OVER
31+ (
32+ PARTITION BY stay_id
33+ ORDER BY seconds_since_admit
34+ RANGE BETWEEN 43200 PRECEDING AND CURRENT ROW
35+ ) AS urineoutput_12hr
36+
37+ , SUM (urineoutput) OVER
38+ (
39+ PARTITION BY stay_id
40+ ORDER BY seconds_since_admit
41+ RANGE BETWEEN 86400 PRECEDING AND CURRENT ROW
42+ ) AS urineoutput_24hr
1443
15- -- 6 hours
16- , sum (case when iosum .charttime >= DATETIME_SUB(io .charttime , interval ' 5' hour)
17- then iosum .urineoutput
18- else null end) as UrineOutput_6hr
19- -- 12 hours
20- , sum (case when iosum .charttime >= DATETIME_SUB(io .charttime , interval ' 11' hour)
21- then iosum .urineoutput
22- else null end) as UrineOutput_12hr
23- -- 24 hours
24- , sum (iosum .urineoutput ) as UrineOutput_24hr
25-
26- -- calculate the number of hours over which we've tabulated UO
27- , ROUND(CAST(
28- DATETIME_DIFF(io .charttime ,
29- -- below MIN() gets the earliest time that was used in the summation
30- MIN (case when iosum .charttime >= DATETIME_SUB(io .charttime , interval ' 5' hour)
31- then iosum .charttime
32- else null end),
33- SECOND) AS NUMERIC )/ 3600 .0 , 4 )
34- AS uo_tm_6hr
35- -- repeat extraction for 12 hours and 24 hours
36- , ROUND(CAST(
37- DATETIME_DIFF(io .charttime ,
38- MIN (case when iosum .charttime >= DATETIME_SUB(io .charttime , interval ' 11' hour)
39- then iosum .charttime
40- else null end),
41- SECOND) AS NUMERIC )/ 3600 .0 , 4 )
42- AS uo_tm_12hr
43- , ROUND(CAST(
44- DATETIME_DIFF(io .charttime , MIN (iosum .charttime ), SECOND)
45- AS NUMERIC )/ 3600 .0 , 4 ) AS uo_tm_24hr
46- from ` physionet-data.mimiciv_derived.urine_output` io
47- -- this join gives all UO measurements over the 24 hours preceding this row
48- left join ` physionet-data.mimiciv_derived.urine_output` iosum
49- on io .stay_id = iosum .stay_id
50- and iosum .charttime <= io .charttime
51- and iosum .charttime >= DATETIME_SUB(io .charttime , interval ' 23' hour)
52- group by io .stay_id , io .charttime
44+ -- repeat the summations using the hours_since_previous_row column
45+ -- this gives us the amount of time the UO was calculated over
46+ , SUM (hours_since_previous_row) OVER
47+ (
48+ PARTITION BY stay_id
49+ ORDER BY seconds_since_admit
50+ RANGE BETWEEN 21600 PRECEDING AND CURRENT ROW
51+ ) AS uo_tm_6hr
52+
53+ , SUM (hours_since_previous_row) OVER
54+ (
55+ PARTITION BY stay_id
56+ ORDER BY seconds_since_admit
57+ RANGE BETWEEN 43200 PRECEDING AND CURRENT ROW
58+ ) AS uo_tm_12hr
59+
60+ , SUM (hours_since_previous_row) OVER
61+ (
62+ PARTITION BY stay_id
63+ ORDER BY seconds_since_admit
64+ RANGE BETWEEN 86400 PRECEDING AND CURRENT ROW
65+ ) AS uo_tm_24hr
66+ from uo_stg1
5367)
5468select
5569 ur .stay_id
@@ -58,15 +72,27 @@ select
5872, ur .urineoutput_6hr
5973, ur .urineoutput_12hr
6074, ur .urineoutput_24hr
61- -- calculate rates - adding 1 hour as we assume data charted at 10:00 corresponds to previous hour
62- , ROUND(CAST((ur .UrineOutput_6hr / wd .weight / (uo_tm_6hr+ 1 )) AS NUMERIC ), 4 ) AS uo_rt_6hr
63- , ROUND(CAST((ur .UrineOutput_12hr / wd .weight / (uo_tm_12hr+ 1 )) AS NUMERIC ), 4 ) AS uo_rt_12hr
64- , ROUND(CAST((ur .UrineOutput_24hr / wd .weight / (uo_tm_24hr+ 1 )) AS NUMERIC ), 4 ) AS uo_rt_24hr
75+
76+ -- calculate rates while requiring UO documentation over at least N hours
77+ -- as specified in KDIGO guidelines 2012 pg19
78+ , CASE
79+ WHEN uo_tm_6hr >= 6 AND uo_tm_6hr < 12
80+ THEN ROUND(CAST((ur .urineoutput_6hr / wd .weight / uo_tm_6hr) AS NUMERIC ), 4 )
81+ ELSE NULL END AS uo_rt_6hr
82+ , CASE
83+ WHEN uo_tm_12hr >= 12
84+ THEN ROUND(CAST((ur .urineoutput_12hr / wd .weight / uo_tm_12hr) AS NUMERIC ), 4 )
85+ ELSE NULL END AS uo_rt_12hr
86+ , CASE
87+ WHEN uo_tm_24hr >= 24
88+ THEN ROUND(CAST((ur .urineoutput_24hr / wd .weight / uo_tm_24hr) AS NUMERIC ), 4 )
89+ ELSE NULL END AS uo_rt_24hr
90+
6591-- number of hours between current UO time and earliest charted UO within the X hour window
6692, uo_tm_6hr
6793, uo_tm_12hr
6894, uo_tm_24hr
69- from ur_stg ur
95+ from uo_stg2 ur
7096left join ` physionet-data.mimiciv_derived.weight_durations` wd
7197 on ur .stay_id = wd .stay_id
7298 and ur .charttime >= wd .starttime
0 commit comments