154 lines
5.6 KiB
MySQL
154 lines
5.6 KiB
MySQL
|
|
-- ------------------------------------------------------------------
|
||
|
|
-- Title: Suspicion of Infection
|
||
|
|
--
|
||
|
|
-- Adapted from the MIMIC-IV upstream
|
||
|
|
-- concepts/sepsis/suspicion_of_infection.sql
|
||
|
|
-- and ported to MIMIC-III v1.3 vanilla PostgreSQL.
|
||
|
|
--
|
||
|
|
-- Definition (from the original Sepsis-3 paper, Seymour 2016):
|
||
|
|
-- a patient is "suspected of infection" if a culture and an
|
||
|
|
-- antibiotic are ordered close in time:
|
||
|
|
-- - culture <= 72 h before antibiotic, OR
|
||
|
|
-- - culture <= 24 h after antibiotic.
|
||
|
|
-- The antibiotic time is taken as the suspected-infection time when
|
||
|
|
-- a culture comes second; the culture time when it comes first.
|
||
|
|
--
|
||
|
|
-- PORT NOTES:
|
||
|
|
-- 1. ID column is `icustay_id`, not `stay_id`.
|
||
|
|
-- 2. MIMIC-III has no `micro_specimen_id`; specimens are identified
|
||
|
|
-- by the tuple (subject_id, hadm_id, chartdate, charttime,
|
||
|
|
-- spec_itemid, spec_type_desc) and we deduplicate organism
|
||
|
|
-- rows by aggregating with that tuple.
|
||
|
|
-- 3. MIMIC-III `prescriptions.startdate` is DATE-precision only.
|
||
|
|
-- Consequently `antibiotic_time` always lands on midnight; the
|
||
|
|
-- MIMIC-IV branches that compare to `me.charttime` still work
|
||
|
|
-- (DATE auto-casts to TIMESTAMP at 00:00) but give day-level
|
||
|
|
-- onset precision.
|
||
|
|
-- ------------------------------------------------------------------
|
||
|
|
|
||
|
|
DROP TABLE IF EXISTS suspicion_of_infection;
|
||
|
|
CREATE TABLE suspicion_of_infection AS
|
||
|
|
|
||
|
|
WITH ab_tbl AS
|
||
|
|
(
|
||
|
|
SELECT abx.subject_id
|
||
|
|
, abx.hadm_id
|
||
|
|
, abx.icustay_id
|
||
|
|
, abx.antibiotic
|
||
|
|
, CAST(abx.starttime AS TIMESTAMP) AS antibiotic_time
|
||
|
|
, CAST(abx.starttime AS DATE) AS antibiotic_date
|
||
|
|
, CAST(abx.stoptime AS TIMESTAMP) AS antibiotic_stoptime
|
||
|
|
, ROW_NUMBER() OVER (
|
||
|
|
PARTITION BY abx.subject_id
|
||
|
|
ORDER BY abx.starttime, abx.stoptime, abx.antibiotic
|
||
|
|
) AS ab_id
|
||
|
|
FROM antibiotic abx
|
||
|
|
)
|
||
|
|
, me AS
|
||
|
|
(
|
||
|
|
SELECT subject_id, hadm_id
|
||
|
|
, spec_itemid
|
||
|
|
, spec_type_desc
|
||
|
|
, MAX(CAST(chartdate AS DATE)) AS chartdate
|
||
|
|
, MAX(charttime) AS charttime
|
||
|
|
, MAX(CASE WHEN org_name IS NOT NULL AND org_name != ''
|
||
|
|
THEN 1 ELSE 0 END) AS positiveculture
|
||
|
|
FROM microbiologyevents
|
||
|
|
GROUP BY subject_id, hadm_id, chartdate, charttime,
|
||
|
|
spec_itemid, spec_type_desc
|
||
|
|
)
|
||
|
|
, me_then_ab AS
|
||
|
|
(
|
||
|
|
SELECT ab_tbl.subject_id
|
||
|
|
, ab_tbl.hadm_id
|
||
|
|
, ab_tbl.icustay_id
|
||
|
|
, ab_tbl.ab_id
|
||
|
|
, COALESCE(me72.charttime,
|
||
|
|
CAST(me72.chartdate AS TIMESTAMP)) AS last72_charttime
|
||
|
|
, me72.positiveculture AS last72_positiveculture
|
||
|
|
, me72.spec_type_desc AS last72_specimen
|
||
|
|
, ROW_NUMBER() OVER (
|
||
|
|
PARTITION BY ab_tbl.subject_id, ab_tbl.ab_id
|
||
|
|
ORDER BY me72.chartdate, me72.charttime NULLS LAST
|
||
|
|
) AS micro_seq
|
||
|
|
FROM ab_tbl
|
||
|
|
LEFT JOIN me me72
|
||
|
|
ON ab_tbl.subject_id = me72.subject_id
|
||
|
|
AND (
|
||
|
|
(
|
||
|
|
me72.charttime IS NOT NULL
|
||
|
|
AND ab_tbl.antibiotic_time > me72.charttime
|
||
|
|
AND ab_tbl.antibiotic_time <= DATETIME_ADD(me72.charttime, INTERVAL '72' HOUR)
|
||
|
|
)
|
||
|
|
OR (
|
||
|
|
me72.charttime IS NULL
|
||
|
|
AND ab_tbl.antibiotic_date >= me72.chartdate
|
||
|
|
AND ab_tbl.antibiotic_date <= me72.chartdate + INTERVAL '3 day'
|
||
|
|
)
|
||
|
|
)
|
||
|
|
)
|
||
|
|
, ab_then_me AS
|
||
|
|
(
|
||
|
|
SELECT ab_tbl.subject_id
|
||
|
|
, ab_tbl.hadm_id
|
||
|
|
, ab_tbl.icustay_id
|
||
|
|
, ab_tbl.ab_id
|
||
|
|
, COALESCE(me24.charttime,
|
||
|
|
CAST(me24.chartdate AS TIMESTAMP)) AS next24_charttime
|
||
|
|
, me24.positiveculture AS next24_positiveculture
|
||
|
|
, me24.spec_type_desc AS next24_specimen
|
||
|
|
, ROW_NUMBER() OVER (
|
||
|
|
PARTITION BY ab_tbl.subject_id, ab_tbl.ab_id
|
||
|
|
ORDER BY me24.chartdate, me24.charttime NULLS LAST
|
||
|
|
) AS micro_seq
|
||
|
|
FROM ab_tbl
|
||
|
|
LEFT JOIN me me24
|
||
|
|
ON ab_tbl.subject_id = me24.subject_id
|
||
|
|
AND (
|
||
|
|
(
|
||
|
|
me24.charttime IS NOT NULL
|
||
|
|
AND ab_tbl.antibiotic_time >= DATETIME_SUB(me24.charttime, INTERVAL '24' HOUR)
|
||
|
|
AND ab_tbl.antibiotic_time < me24.charttime
|
||
|
|
)
|
||
|
|
OR (
|
||
|
|
me24.charttime IS NULL
|
||
|
|
AND ab_tbl.antibiotic_date >= me24.chartdate - INTERVAL '1 day'
|
||
|
|
AND ab_tbl.antibiotic_date <= me24.chartdate
|
||
|
|
)
|
||
|
|
)
|
||
|
|
)
|
||
|
|
SELECT ab_tbl.subject_id
|
||
|
|
, ab_tbl.icustay_id
|
||
|
|
, ab_tbl.hadm_id
|
||
|
|
, ab_tbl.ab_id
|
||
|
|
, ab_tbl.antibiotic
|
||
|
|
, ab_tbl.antibiotic_time
|
||
|
|
|
||
|
|
, CASE
|
||
|
|
WHEN me2ab.last72_specimen IS NULL AND ab2me.next24_specimen IS NULL
|
||
|
|
THEN 0 ELSE 1
|
||
|
|
END AS suspected_infection
|
||
|
|
|
||
|
|
, CASE
|
||
|
|
WHEN me2ab.last72_specimen IS NULL AND ab2me.next24_specimen IS NULL
|
||
|
|
THEN NULL
|
||
|
|
ELSE COALESCE(me2ab.last72_charttime, ab_tbl.antibiotic_time)
|
||
|
|
END AS suspected_infection_time
|
||
|
|
|
||
|
|
, COALESCE(me2ab.last72_charttime, ab2me.next24_charttime) AS culture_time
|
||
|
|
, COALESCE(me2ab.last72_specimen, ab2me.next24_specimen) AS specimen
|
||
|
|
, COALESCE(me2ab.last72_positiveculture,
|
||
|
|
ab2me.next24_positiveculture) AS positive_culture
|
||
|
|
FROM ab_tbl
|
||
|
|
LEFT JOIN ab_then_me ab2me
|
||
|
|
ON ab_tbl.subject_id = ab2me.subject_id
|
||
|
|
AND ab_tbl.ab_id = ab2me.ab_id
|
||
|
|
AND ab2me.micro_seq = 1
|
||
|
|
LEFT JOIN me_then_ab me2ab
|
||
|
|
ON ab_tbl.subject_id = me2ab.subject_id
|
||
|
|
AND ab_tbl.ab_id = me2ab.ab_id
|
||
|
|
AND me2ab.micro_seq = 1;
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS suspicion_of_infection_idx
|
||
|
|
ON suspicion_of_infection (icustay_id, suspected_infection_time);
|