2014-10-10 3 views
0

У меня есть таблица ENCOUNTERS в 11g базы данных Oracle, данные выборки здравоохранения,SQL Само Subquery Улучшение

ID DC_DATE CPI 
1 "1/1/2012" a 
2 "1/2/2012" b 
3 "1/3/2012" c 
4 "1/4/2012" d 
5 "2/2/2012" a 
6 "2/1/2012" b 
7 "2/3/2012" e 
8 "2/4/2012" f 
9 "2/5/2012" g 
10 "2/29/2012" a 

ID представляет собой уникальный идентификатор посещения для человека и ИВК является Person ID, который отслеживает, когда люди приходят посетить нас снова в более поздние даты.

Мне было поручено создать запрос, который возвращает все эти столбцы плюс три новых столбца, PREVIOUS_ID, PREVIOUS_DC_DATE, and READMIT_DAYS Readmit_Days - разница в днях между новыми посещениями DC_Date и их предыдущими посещениями DC_Date.

В настоящее время мне нужно запустить следующий код, чтобы получить нужные мне данные.

SELECT a.ID, 
     a.DC_DATE, 
     a.CPI, 
     (SELECT MAX(b.ID) 
     FROM ENCOUNTERS b 
     WHERE a.CPI = b.CPI 
       AND a.ID > b.ID)        AS Previous_ID, 
     (SELECT MAX(b.DC_DATE) 
     FROM ENCOUNTERS b 
     WHERE a.CPI = b.CPI 
       AND a.DC_DATE > b.DC_DATE)     AS Previous_DC_Date, 
     (a.DC_DATE - ((SELECT MAX(b.DC_DATE) 
         FROM ENCOUNTERS b 
         WHERE a.CPI = b.CPI 
           AND a.DC_DATE > b.DC_DATE))) AS ReAdmit_Days 
FROM ENCOUNTERS a; 

Теперь это работает, но для меня это выглядит слишком сложно. Есть ли лучший способ получить то, что мне нужно?

Это то, что я получаю, когда оно работает, что является правильным. Просто ищите предложения.

ID DC_DATE CPI Previous_ID Previous_DC_Date Readmit_Days 
1 "1/1/2012" a   
2 "1/2/2012" b   
3 "1/3/2012" c   
4 "1/4/2012" d   
5 "2/2/2012" a 1 "1/1/2012" 32 
6 "2/1/2012" b 2 "1/2/2012" 30 
7 "2/3/2012" e   
8 "2/4/2012" f   
9 "2/5/2012" g   
10 "2/29/2012" a 5 "2/2/2012" 27 

ответ

1
with encounters as (
select 1 id, to_date('01/01/2012', 'MM/DD/YYYY') dc_date, 'a' cpi from dual union all 
select 2, to_date('01/02/2012', 'MM/DD/YYYY'), 'b' from dual union all 
select 3, to_date('01/03/2012', 'MM/DD/YYYY'), 'c' from dual union all 
select 4, to_date('01/04/2012', 'MM/DD/YYYY'), 'd' from dual union all 
select 5, to_date('02/02/2012', 'MM/DD/YYYY'), 'a' from dual union all 
select 6, to_date('02/01/2012', 'MM/DD/YYYY'), 'b' from dual union all 
select 7, to_date('02/03/2012', 'MM/DD/YYYY'), 'e' from dual union all 
select 8, to_date('02/04/2012', 'MM/DD/YYYY'), 'f' from dual union all 
select 9, to_date('02/05/2012', 'MM/DD/YYYY'), 'g' from dual union all 
select 10, to_date('02/29/2012', 'MM/DD/YYYY'), 'a' from dual) 
select id, dc_date, cpi, previous_id, previous_dc_date, dc_date - previous_dc_date readmit_days 
from 
(select id, dc_date, cpi, 
     max(id) over (partition by cpi order by id range between unbounded preceding and 1 preceding) as previous_id, 
     max(dc_date) over (partition by cpi order by dc_date rows between unbounded preceding and 1 preceding) as previous_dc_date 
    from encounters); 

Аналитические функции лучше. В вашем запросе вы делаете много дополнительных коррелированных запросов.

P.S. Второе окно (которое использует оконные окна dc_date и «rows») не будет корректно работать со связками. Здесь вы можете использовать «диапазон» и интервалы. Это просто пример.

+0

Очень интересно. Я рассмотрю ключевые слова, которые вы используете. Я никогда не использовал и не разбивал. Я все еще пытаюсь склонить голову вокруг того, как это работает. благодаря – Scheballs