SQL выбирайте лекарства только при заражении covid - PullRequest
0 голосов
/ 19 июня 2020

У меня 2 стола. В таблице lab_obs записываются результаты тестирования пациента на covid. В таблице «лекарства» содержатся записи обо всех лекарствах, принимаемых всеми пациентами (независимо от того, прошли ли они тестирование). Вот упрощенная схема:

CREATE TABLE lab_obs (ob_day DATE, 
                          ob VARCHAR(20),
                          patient_id VARCHAR(20)
                         );

CREATE TABLE medications (given_day DATE, 
                          med VARCHAR(20),
                          patient_id VARCHAR(20)
                         );                         

INSERT INTO lab_obs VALUES ('2020-03-01', 'positive', 'p11');
INSERT INTO lab_obs VALUES ('2020-05-01', 'negative', 'p11');
INSERT INTO lab_obs VALUES ('2020-03-02', 'negative', 'p12');
INSERT INTO lab_obs VALUES ('2020-06-01', 'negative', 'p11');
INSERT INTO lab_obs VALUES ('2020-06-01', 'negative', 'p12');

INSERT INTO medications VALUES ('2020-03-05', 'covid_med_11', 'p11');
INSERT INTO medications VALUES ('2020-03-05', 'non_covid_med_12', 'p12');
INSERT INTO medications VALUES ('2020-02-05', 'non_covid_med_11', 'p11');
INSERT INTO medications VALUES ('2020-04-05', 'non_covid_med_41', 'p41');

Я хочу написать SQL, который даст мне (идентификатор_палента, med) для пациентов с положительным результатом и впоследствии отрицательным, а также все лекарства, принимаемые в период между положительный тест и последующий отрицательный тест. По сути, запрос должен дать мне все лекарства, которые принимали пациенты, выздоровевшие от Covid !!

Ответы [ 3 ]

1 голос
/ 19 июня 2020

Пробовал с PostgreSQL (не уверен, какую СУБД вы используете). Для этого вам понадобятся оконные функции и CTE:

WITH lagged_obs AS (
    SELECT patient_id,
           ob_day,
           ob,
           LAG(ob) OVER (PARTITION BY patient_id ORDER BY ob_day) AS lagged_ob
    FROM lab_obs
)
, patient_status_change AS (
    -- Look for status changes, useful for consecutive tests with same result
    SELECT patient_id,
           ob_day AS ob_change_day,
           ob
    FROM lagged_obs
    WHERE ob IS DISTINCT FROM lagged_ob
)
, patient_infected_periods AS (
    -- Build time periods
    SELECT patient_id,
           ob_change_day AS start_date,
           LEAD(ob_change_day)
               OVER (PARTITION BY patient_id ORDER BY ob_change_day) AS end_date,
           ob AS period_status
    FROM patient_status_change
)
SELECT pip.patient_id, m.given_day, m.med
FROM patient_infected_periods pip
    INNER JOIN medications m
    ON pip.patient_id=m.patient_id AND pip.start_date <= m.given_day AND m.given_day < pip.end_date
WHERE pip.period_status='postive'
1 голос
/ 19 июня 2020

Это немного сложно. Если кто-то дал положительный результат только один раз, то:

select m.*
from medications m
where m.given_day >= (select min(l.ob_day)
                      from lab_obs l
                      where l.patient_id = m.patient_id and l.ob = 'positive'
                     ) and
      m.given_day < (select min(l.ob_day)
                     from (select l.*, min(case when ob = 'positive' then ob_day end) as pos_ob_day
                           from lab_obs l
                          ) l
                     where l.patient_id = m.patient_id and
                           l.ob = 'negative' and
                           l.ob_date > pos_ob_day
                        );

Это работает для отрицательно-положительно-отрицательного и положительно-отрицательного сценария ios.

Если кто-то может переключаться вперед и назад, я бы предложил использовать lag() следующим образом:

select m.*, l.*
from medications m join
     (select l.*,
             lead(ob_day) over (partition by patient_id order by ob_day) as next_ob_day
      from (select l.*,
                   lag(ob) over (partition by patient_id order by ob_day) as prev_ob
           from lab_obs l
          ) l
      where prev_ob is null or prev_ob <> ob
     ) l
     on m.patient_id = l.patient_id and
        m.given_date >= l.ob_day and
        m.given_date < l.next_ob_day and
        l.ob = 'positive';

Подзапрос l определяет, когда кто-то сначала дает положительный результат, а затем следующий дата теста с другим значением теста.

1 голос
/ 19 июня 2020

Думаю, это то, что вы могли бы использовать. Использование функции задержки для проверки предыдущей записи. Я запустил его на сервере SQL. Кроме того, пожалуйста, используйте коды для наблюдения, поскольку написание может вызвать проблемы, например, положительный, а не положительный.

SELECT m.patient_id, m.med , m.given_day
FROM medications m
JOIN (SELECT patient_id, 
       CASE WHEN ob = 'negative'
             AND lag(ob) OVER (partition by patient_id order by l.ob_day) = 'postive'
            THEN 1
            ELSE 0 
            END as qualify
      FROM lab_obs l) l ON l.patient_id = m.patient_id AND l.qualify = 1
...