Отображение ближайших дат в Oracle - PullRequest
0 голосов
/ 23 января 2019

enter image description here Я пытаюсь объединить две таблицы в ближайшее время.Пожалуйста, смотрите скриншот для справки.

У меня есть Лекарство Таблица и Побочные эффекты Таблица, и мне нужно знать, в каком медицинском месте находится конкретный побочный эффект.

Пример 1: Медикаментозное лечение началось 2015-07-23 (2-я строка в Таблице медикаментов), а на 2015-07-24 было побочное действие (2-я строка в Таблице побочных эффектов).Таким образом, это говорит мне о том, что медицинское местоположение: АБДОМЕН .

Пример 2: Лекарство началось 2018-06-19 (последняя строка в Таблице лекарств) и былоПобочное воздействие на 2018-07-25 (последняя строка в Таблице побочных эффектов).Таким образом, это говорит мне, что медицинское местоположение: THIGH .

Итак, я просто пытаюсь отобразить ближайшие даты обеих таблиц и получить конкретный медицинскийРасположение в итоговой таблице.

Когда я пишу соединение следующим образом: MID = SID И MNAME = SNAME AND Дата начала лечения <= Дата побочного эффекта, тогда я получаю слишком много записей.Похоже, мне не хватает условия, чтобы написать здесь.Не могли бы вы помочь мне в этом. </p>

Спасибо.

Medication Table:
MID     MNAME       MedicalLocation   Medication Start Date
I1F-BE  132~1201    THIGH             2015-07-07
I1F-BE  132~1202    ABDOMEN           2015-07-23
I1F-BE  132~1203    ABDOMEN           2015-08-04
I1F-BE  132~1204    ABDOMEN           2015-08-18
I1F-BE  132~1205    ABDOMEN           2015-09-01
I1F-BE  132~1206    ABDOMEN           2015-09-15
I1F-BE  132~1207    ABDOMEN           2015-09-29
I1F-BE  132~1208    ABDOMEN           2015-10-13
I1F-BE  132~1209    THIGH             2015-10-27
I1F-BE  132~1210    ABDOMEN           2015-11-10
I1F-BE  132~1201    THIGH             2018-06-19
I1F-BE  132~1209    THIGH             2015-10-27
I1F-BE  132~1210    ABDOMEN           2015-11-10
I1F-BE  132~1201    THIGH             2018-06-19

Таблица побочных эффектов:

SID     SNAME        Side Effect             Side Effect Start Date
I1F-BE  132~1201    UTI                      2015-06-23
I1F-BE  132~1202    Injection Site Reaction  2015-07-24
I1F-BE  132~1203    Injection Site Reaction  2015-08-05
I1F-BE  132~1204    Viral Syndrome           2015-08-10
I1F-BE  132~1205    Injection Site Reaction  2015-08-18
I1F-BE  132~1206    Injection Site Reaction  2015-09-02
I1F-BE  132~1207    Injection Site Reaction  2015-09-16
I1F-BE  132~1208    Injection Site Reaction  2015-09-30
I1F-BE  132~1209    Injection Site Reaction  2015-10-14
I1F-BE  132~1210    Injection Site Reaction  2015-10-28
I1F-BE  132~1201    Basal Cell carcinoma     2018-07-25

Ответы [ 2 ]

0 голосов
/ 23 января 2019

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

Альтернативный подход, который должен масштабироваться, использует унифицированное представление для обеих таблиц с аналитической функцией поиска в записи LAG ing, чтобы получить местоположение.

По этому запросу создается унифицированное представление. Обратите внимание, что для выделения источника строки добавлен новый столбец SOURCE_TYPE.

with tab as (
select SID, SNAME, START_DATE, 'SIDE_EFFECT' source_type,cast (null as varchar2(25)) MEDICALLOCATION,  SideEffect from SideEffect
union all
select MID, MNAME, START_DATE, 'MEDICATION' source_type, MEDICALLOCATION, null as SideEffect from Medication
)
select SID, SNAME, START_DATE, SOURCE_TYPE, MEDICALLOCATION, SIDEEFFECT 
from tab
where SID = 'I1F-BE' and SNAME = '132~1202'
order by 1,2,3;

SID        SNAME      START_DATE          SOURCE_TYPE MEDICALLOCATION           SIDEEFFECT              
---------- ---------- ------------------- ----------- ------------------------- -------------------------
I1F-BE     132~1202   23.07.2015 00:00:00 MEDICATION  ABDOMEN                                             
I1F-BE     132~1202   24.07.2015 00:00:00 SIDE_EFFECT                           Injection Site Reaction   

Единственная дополнительная логика, необходимая для записи SIDE_EFFECT, если перед ней непосредственно стоит запись MEDICATION, чтобы получить значение столбца MEDICALLOCATION из запаздывающей записи.

Аналитическая функция LAG использует PARTITION BY в столбцах ключей объединения, а ORDER BY определяется start_date.

После перемещения местоположения в строку site_effect вы можете отказаться от всех записей лекарств.

Окончательный запрос

with tab as (
select SID, SNAME, START_DATE, 'SIDE_EFFECT' source_type,cast (null as varchar2(25)) MEDICALLOCATION,  SideEffect from SideEffect
union all
select MID, MNAME, START_DATE, 'MEDICATION' source_type, MEDICALLOCATION, null as SideEffect from Medication
),
tab2 as (
select SID, SNAME, START_DATE, SOURCE_TYPE, MEDICALLOCATION,  SIDEEFFECT,
CASE when SOURCE_TYPE = 'SIDE_EFFECT' and
          lag(SOURCE_TYPE) over (partition by  SID, SNAME order by START_DATE) = 'MEDICATION' then 
     lag(MEDICALLOCATION) over (partition by  SID, SNAME order by START_DATE)
END as SIDEEFFECT_MEDICALLOCATION  
from tab)
select SID, SNAME, START_DATE, SIDEEFFECT, SIDEEFFECT_MEDICALLOCATION 
from tab2
where source_type = 'SIDE_EFFECT' 
order by 1,2,3;

SID        SNAME      START_DATE          SIDEEFFECT                SIDEEFFECT_MEDICALLOCATION
---------- ---------- ------------------- ------------------------- --------------------------
I1F-BE     132~1201   23.06.2015 00:00:00 UTI                                                  
I1F-BE     132~1201   25.07.2018 00:00:00 Basal Cell carcinoma      THIGH                      
I1F-BE     132~1202   24.07.2015 00:00:00 Injection Site Reaction   ABDOMEN                    
I1F-BE     132~1203   05.08.2015 00:00:00 Injection Site Reaction   ABDOMEN                    
I1F-BE     132~1204   10.08.2015 00:00:00 Viral Syndrome  
...
0 голосов
/ 23 января 2019

Звучит так, как будто вы хотите получить строку из таблицы лекарств, в которой максимальная дата лекарства <= дата побочного эффекта.Это довольно распространенный шаблон SQL: см. <a href="/80270/izvlech-stroku-kotoraya-imeet-znachenie-max-dlya-stolbtsa"> этот вопрос для примера с некоторыми замечательными ответами.

У меня есть несколько предложений для вас.Первый способ - наивный способ написать это - он будет работать на всех версиях Oracle.Один из возможных вопросов для рассмотрения: что вы хотите, чтобы произошло, когда «ближайшая дата» соответствует ДВУМ лекарствам с одинаковыми датами начала?Этот запрос будет возвращать по одной строке для каждого совпадения, что может оказаться больше, чем вы ожидаете.

select s.*, m.MedicalLocation
from side_effects s
left join medication m
  on m.mid = s.sid
  and m.mname = s.sname
  and m.medication_start_date = (
    select max(medication_start_date)
    from medication m2
    where m2.mid = m.mid
      and m2.mname = m.mname
      and m2.medication_start_date <= s.side_effect_date)
;

Вы также можете написать это несколько проще в Oracle 12c и выше, используя предложение fetch first 1 row only.Это гарантирует, что вы получите только 1 запись лекарства для каждого побочного эффекта - если у вас есть два совпадения, Oracle просто выберет одну в зависимости от того, как расположены строки на диске.

select s.*, 
    (select m.MedicalLocation
     from medication m
     where m.mid = s.sid
       and m.mname = s.sname
       and m.medication_start_date <= s.side_effect_date
     order by m.medication_start_date desc
     fetch first 1 row only) as MedicalLocation
from side_effects s
;

Вы также можете проверить другие ответы на вопрос, который я связал, для других способов сделать это, например,

select s.*, max(m.MedicalLocation) KEEP (DENSE_RANK FIRST ORDER BY m.medication_start_date desc) as MedicalLocation
from side_effects s
left join medication m
  on m.mid = s.sid
  and m.mname = s.sname
  and m.medication_start_date <= s.side_effect_date
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...