Обнаружение дубликатов, которые выходят за пределы интервала дат - PullRequest
2 голосов
/ 25 августа 2011

Я искал в SO, но не смог найти прямой ответ.

Есть пациенты, больницы, медицинские отделения (ER, урология, ортопедия, болезни внутренних органов и т. Д.), Коды медицинских операций (обследование, хирургическая операция, МРТ, УЗИ или иное) и даты посещения пациента.

Пациент посещает врача, врач выписывает лекарство и просит прийти снова для контрольной проверки.Если пациент возвращается через 10 дней, он должен заплатить еще один сбор за обследование в ту же больницу.Больницы могут назначить дату через 10 дней, сообщая об отсутствии свободных мест в следующие 10 дней, чтобы получить плату за экзамен.

Структура таблицы выглядит следующим образом:

Patient id.no   Hospital    Medical Branch     Medical Op. Code      Date
  1                 H1             M0                P1            01/05/2011
  5                 H1             M1                P9            03/05/2011
  3                 H2             M0                P2            09/05/2011
  1                 H1             M0                P1            14/05/2011 
  3                 H1             M0                P2            20/05/2011
  5                 H1             M2                P9            25/05/2011
  1                 H1             M0                P3            26/05/2011

Здесь, посещениепациентов нет.3 и 5 не представляет проблемы, так как пациент нет.3 посещения разных больниц, а пациент № 5 посещает разные медицинские отделения.Они будут платить за экзамен, даже если будут посещать его в течение 10 дней.

Пациент № 1, однако, посещает одну и ту же больницу, одно и то же отделение и подвергается той же процедуре (P1: обследование) 01/05 и 14/ 05.

26/05 не считается, потому что это не медицинское обследование.

Я хочу пометить того же пациента, ту же больницу, ту же ветвь и тот же код медицинской операции (то есть конкретно медицинское обследование:P1), с диапазоном дат более 10 дней.

Формат результирующей таблицы:

HOSPITAL        TOTAL NUM. of PATIENTS      NUM. of PATIENTS OUT OF DATE RANGE
  H1                        x                              a
  H2                        y                              b
  H3                        z                              c

Спасибо.

Ответы [ 3 ]

2 голосов
/ 25 августа 2011

Еще раз, это аналитические функции на помощь.

Этот запрос использует функцию LAG (), чтобы связать запись в YOUR_TABLE с предыдущей (определенной DATE) совпадающей записью (определенной PATIENT_ID) в таблице.

select hospital_id
       , count(*) as total_num_of_patients      
       , sum (out_of_range) as num_of_patients_out_of_range
from (
    select patient_id
           , hospital_id
           , case
                   when hospital_id_1 = hospital_id_0
                   and  visit_1 > visit_0 + 10
                   and  med_op_code_1 = med_op_code_0
                   then 1
                   else 0
              end as out_of_range
    from (
            select patient_id
                   , hospital_id as hospital_id_1
                   , date as visit_1
                   , med_op_code as med_op_code_1
                   , lag (date) over (partition by patient_id order by date) as visit_0
                   , lag (hopital_id) over (partition by patient_id order by date) as hopital_id_0
                   , lag (med_op_code) over (partition by patient_id order by date) as med_op_code_0
            from your_table
            where med_op_code = 'P1'
        )
    )
group by hospital_id
/

Предупреждение: я не тестировал этот код, поэтому он может содержать синтаксические ошибки. Я проверю это в следующий раз, когда смогу получить доступ к базе данных Oracle.

1 голос
/ 25 августа 2011

Я думаю, это то, что вы пытаетесь:

WITH Patient_Visits (Patient_Id, Hospital_Id, Branch_Id, Visit_Date, Visit_Order) as ( 
                     SELECT Patient_Id, Hospital_Id, BranchId, Visit_Date, 
                            ROW_NUMBER() OVER(PARTITION BY Patient_ID, Hospital_Id, Branch_Id, 
                                              ORDER_BY Patient_Id, Hospital_Id, Branch_Id, Visit_Date)
                    FROM Hospital_Visits
                    WHERE Procedure_Id = 'P1'),
     Hospital_Recent_Visits (Hospital_Id, Recent_Visitor_Count) as (
                             SELECT a.Hospital_Id, COUNT(DISTINCT a.Patient_Id)
                             FROM Patient_Visits as a
                             JOIN Patient_Visits as b
                               ON b.Hospital_Id = a.Hospital_Id
                                  AND b.Branch_Id = a.Branch_Id
                                  AND b.Patient_Id = a.Patient_Id
                                  AND b.Visit_Order = a.Visit_Order - 1
                                  AND b.Visit_Date + 10 > a.Visit_Date
                             GROUP BY a.Hospital_Id, a.Patient_Id),
     Hospital_Patient_Count (Hospital_Id, Patient_Count) as (
                             SELECT Hospital_Id, COUNT(DISTINCT Patient_Id)
                             FROM Hospital_Visits
                             GROUP BY Hospital_Id, Patient_Id)
SELECT a.Hospital_Id, b.Patient_Count, c.Recent_Visitor_Count
FROM Hospitals as a
LEFT JOIN Hospital_Patient_Count as b
ON b.Hospital_Id = a.Hospital_Id
LEFT JOIN Hospital_Recent_Visits as c
ON c.Hospital_id = a.Hospital_Id

Обратите внимание, что это было написано и проверено на системе DB2.Я думаю, что базы данных Oracle имеют соответствующую функциональность, поэтому запрос все равно должен работать как написано.Однако в DB2, похоже, отсутствуют некоторые функции OLAP, которые есть у Oracle (по крайней мере, в моей версии), что может быть полезно для выбивания некоторых из CTE.

1 голос
/ 25 августа 2011

Это немного грубо, так как у меня нет базы данных Oracle, но ключевая особенность та же: аналитическая функция LAG (). Наряду с сопутствующей функцией LEAD () они отлично помогают справляться с такими вещами, как периоды активности.

Вот моя попытка кода:

select n.hospital, COUNT(n.patient_id) as patients_out_of_date_range
from (
    select *
    from (
        select d.*, lag(date, 1) over (partition by d.patient_id, d.hospital, d.medical_branch, d.medical_op_code order by d.date) as prev_date
        from datatable d inner join
            (
                select d.patient_id, d.hospital, d.medical_branch, d.medical_op_code
                from datatable d
                where d.medical_op_code = 'P1'
                group by d.patient_id, d.hospital, d.medical_branch, d.medical_op_code
                having COUNT(d.date) > 1
            ) t on d.patient_id  = t.patient_id and d.hospital = t.hospital and d.medical_branch = t.medical_branch and d.medical_op_code = t.medical_op_code
        ) m
    where date - prev_date > 10
    ) n
group by n.hospital

Как я уже сказал, это не проверено, но, по крайней мере, должно привести вас в правильное русло.

Некоторые ссылки: http://www.adp -gmbh.ch / ор / SQL / аналитический / lag.html

http://www.oracle -base.com / Статьи / разное / LagLeadAnalyticFunctions.php

...