SQL自子查询改进

时间:2014-10-10 01:19:36

标签: sql oracle subquery

我在Oracle 11g数据库中有一个表ENCOUNTERS,样本医疗保健数据

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是一个人的唯一访问标识符,CPI是一个人员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 个答案:

答案 0 :(得分: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和"行"窗口)不能正常工作。您可以使用" range"和间隔在这里。这只是一个例子。