Search code examples
sqlsql-serverthreshold

SQL Server episode identification


I am working with a blood pressure database in SQL Server which contains patient_id, timestamp (per minute) and systolicBloodPressure.

My goals are to find:

  1. the number of episodes in which a patient is under a certain blood pressure threshold

    An episode consists of the timestmap where the patient drops below a certain threshold until the timestamp where the patient comes above the threshold.

  2. the mean blood pressure per episode per patient

  3. the duration of the episode per episode per patient

What I have tried so far:

I am able to identify episodes by just making a new column which sets to 1 if threshold is reached.

    select *
    , CASE
    when sys < threshold THEN '1'
    from BPDATA

However , I am not able to 'identify' different episodes within the patient; episode1 episode 2 with their relative timestamps.

Could someone help me with this? Or is there someone with a better different solution?

EDIT: Sample data with example threshold 100

    ID          Timestamp      SysBP      below Threshold
    ----------------------------------------------------
    1             9:38          110       Null
    1             9:39          105       Null
    1             9:40          96        1
    1             9:41          92        1 
    1             9:42          102       Null
    2             12:23         95        1
    2             12:24         98        1
    2             12:25         102       Null
    2             12:26         104       Null
    2             12:27         94        1
    2             12:28         88        1  
    2             12:29         104       Null

Solution

  • Thanks for the sample data.

    This should work:

    declare @t table (ID int, Timestamp time, SysBP int, belowThreshold bit)
    insert @t 
    values
    (1,              '9:38',          110, null),
    (1,              '9:39',          105, null),
    (1,              '9:40',           96, 1),
    (1,              '9:41',           92, 1),
    (1,              '9:42',          102, null),
    (2,             '12:23',           95, 1),
    (2,             '12:24',           98, 1),
    (2,             '12:25',          102, null),
    (2,             '12:26',          104, null),
    (2,             '12:27',           94, 1),
    (2,             '12:28',           88, 1),
    (2,             '12:29',          104, null)
    
    declare @treshold int = 100
    
    ;with y as (
        select *, case when lag(belowThreshold, 1, 0) over(partition by id order by timestamp) = belowThreshold then 0 else 1 end epg
        from @t
    ),
    z as (
        select *, sum(epg) over(partition by id order by timestamp) episode
        from y
        where sysbp < @treshold
    )
    select id, episode, count(episode) over(partition by id) number_of_episodes_per_id, avg(sysbp) avg_sysbp, datediff(minute, min(timestamp), max(timestamp))+1 episode_duration
    from z
    group by id, episode