2013-04-17 178 views
0

我試圖找到在另一個日期/時間值的24小時內發生的第一個日期/時間值。SQL:另一日期/時間的24小時內的最小日期/時間值

ENCOUNTER表:

ENC_ID ADMSN_TIME   DISCH_TIME 
16755387 03/19/13 11:10:00 03/22/13 12:55:00 

PROBLEM_LIST表:

ENC_ID  REVIEWED_TIME  USER_ID 
16755387 03/19/13 13:02:00 FOOBAR 
16755387 03/19/13 13:03:00 FOOBAR 
16755387 03/20/13 07:52:00 FOOBAR 
16755387 03/22/13 08:35:00 FOOBAR 
16755387 03/22/13 08:35:00 FOOBAR 
16755387 03/22/13 08:35:00 FOOBAR 

所需的結果集:

ENC_ID ADMSN_TIME   ADMSN_REVIEW_TIME ADMSN_REVIEWER DISCH_REVIEW_TIME DISCH_REVIEWER 
16755387 03/19/13 11:10:00 03/19/13 13:02:00 FOOBAR   03/22/13 08:35:00 FOOBAR 

規則:

  1. ABS(REVIEWED_TIME - ADMSN_TIME)< = 1個
  2. ABS(REVIEWED_TIME - DISCH_TIME)< = 1
  3. 可能不存在對應於入院時,或放電的審查時間,或兩者

我的第一嘗試:

SELECT E.ENC_ID, 

     E.ADMSN_TIME, 
     R0.REVIEWED_TIME ADMSN_REVIEWED_TIME, 
     R0.USER_ID ADMSN_REVIEWER, 

     E.DISCH_TIME, 
     R1.REVIEWED_TIME DISCH_REVIEWED_TIME, 
     R1.USER_ID DISCH_REVIEWER 

FROM ENCOUNTER E 
INNER JOIN PROBLEM_LIST R0 ON HE.ENC_ID=R0.ENC_ID 
    and r0.REVIEWED_TIME = (
    SELECT MIN(REVIEWED_TIME) 
    FROM PROBLEM_LIST 
    WHERE ENC_ID=E.ENC_ID 
    AND  ABS(REVIEWED_TIME - ADMSN_TIME)<=1  
    ) 
INNER JOIN PROBLEM_LIST R1 ON E.ENC_ID=R1.ENC_ID 
    and r1.REVIEWED_TIME = (
    SELECT MIN(REVIEWED_TIME) 
    FROM PROBLEM_LIST 
    WHERE ENC_ID=E.ENC_ID 
    AND  ABS(REVIEWED_TIME - DISCH_TIME)<=1  
    ) 

問題:

  • 沒有異體w缺少評論(規則#3);用「OUTER JOIN」生成語法錯誤
  • 不消除重複PROBLEM_LIST記錄

有沒有一種方法,使這項工作?

**編輯**

SELECT DISTINCT ENC_ID, 
     E.ADMSN_TIME, 
     FIRST_VALUE(R0.REVIEWED_TIME) OVER (PARTITION BY R0.ENC_ID ORDER BY R0.REVIEWED_TIME) ADMSN_REVIEWED_TIME, 
     FIRST_VALUE(R0.USER_ID) OVER (PARTITION BY R0.ENC_ID ORDER BY R0.REVIEWED_TIME) ADMSN_REVIEWED_BY, 
     E.DISCH_TIME, 
     FIRST_VALUE(R1.REVIEWED_TIME) OVER (PARTITION BY R1.ENC_ID ORDER BY R1.REVIEWED_TIME) DISCH_REVIEWED_TIME 
     ,FIRST_VALUE(R1.USER_ID) OVER (PARTITION BY R1.ENC_ID ORDER BY R1.REVIEWED_TIME) DISCH_REVIEWED_BY 

FROM ENCOUNTER E 
LEFT JOIN PROBLEM_LIST R0 ON E.ENC_ID=R0.ENC_ID 
    AND ABS(r0.REVIEWED_TIME - ADMSN_TIME)<=1 
LEFT OUTER JOIN PROBLEM_LIST R1 ON E.ENC_ID=R1.ENC_ID 
    AND ABS(R1.REVIEWED_TIME - DISCH_TIME)<=1 

根據需要,但DISTINCT條款似乎並不是最佳的,這個方法工作。有沒有更高效的查詢?

+0

你說你想要的最低,這表明我應該在你的查詢某處查看min()函數。 –

+0

@DanBracuk,子選擇中有一個「MIN」。'SELECT MIN(REVIEWED_TIME)...' – craig

回答

0

我想出了下面,它適用於幾個測試。使用LEAD分析功能和一個UNION。

SELECT enc_id, 
     admsn_time, 
     CASE 
      WHEN TO_CHAR (admsn_time, 'DDMMYYYY') = 
        TO_CHAR (admsn_review_time, 'DDMMYYYY') 
      THEN 
      admsn_review_time 
      ELSE 
      NULL 
     END 
      AS admsn_review_time, 
     CASE 
      WHEN TO_CHAR (admsn_time, 'DDMMYYYY') = 
        TO_CHAR (admsn_review_time, 'DDMMYYYY') 
      THEN 
      admsn_user 
      ELSE 
      NULL 
     END 
      AS admsn_review_user, 
     disch_time, 
     CASE 
      WHEN TO_CHAR (disch_time, 'DDMMYYYY') = 
        TO_CHAR (disch_review_time, 'DDMMYYYY') 
      THEN 
      disch_review_time 
      ELSE 
      NULL 
     END 
      AS disch_review_time, 
     CASE 
      WHEN TO_CHAR (disch_time, 'DDMMYYYY') = 
        TO_CHAR (disch_review_time, 'DDMMYYYY') 
      THEN 
      disch_user 
      ELSE 
      NULL 
     END 
      AS disch_review_user 
    FROM (SELECT enc_id, 
       admsn_time, 
       LEAD (admsn_time, 1) 
        OVER (PARTITION BY enc_id ORDER BY admsn_time) 
        admsn_review_time, 
       LEAD (user_id, 1) 
        OVER (PARTITION BY enc_id ORDER BY admsn_time) 
        admsn_user, 
       disch_time, 
       LEAD (disch_time, 1) 
        OVER (PARTITION BY enc_id ORDER BY disch_time) 
        disch_review_time, 
       LEAD (user_id, 1) 
        OVER (PARTITION BY enc_id ORDER BY disch_time) 
        disch_user, 
       ch 
      FROM (SELECT e.enc_id, 
         admsn_time, 
         disch_time, 
         'E' AS ch, 
         NULL AS user_id 
        FROM encounter e 
       UNION 
       SELECT enc_id, 
         reviewed_time, 
         reviewed_time, 
         'P', 
         user_id 
        FROM problem_list pl)) 
WHERE ch = 'E'; 
0

不知道這將是比任何你的整體第二種方案更有效,但它避免了distinct和兩個加入到problem_list。還是覺得過於複雜的 - 做一個unpivot後跟一個pivot似乎是一個黑客 - 但它的部分原因是我自己的娛樂:

select enc_id, admsn_time, admsn_review_time, admsn_reviewer, 
    disch_time, disch_review_time, disch_reviewer 
from (
    select enc_id, admsn_time, disch_time, user_id, reviewed_time, review_type 
    from (
     select * 
     from (
      select e.enc_id, e.admsn_time, e.disch_time, 
       pl.user_id, pl.reviewed_time, 
       row_number() over (partition by e.enc_id 
        order by abs(pl.reviewed_time - e.admsn_time)) 
         as admsn_reviewed_rn, 
       row_number() over (partition by e.enc_id 
        order by abs(pl.reviewed_time - e.disch_time)) 
         as disch_reviewed_rn 
      from encounter e 
      left join problem_list pl on pl.enc_id = e.enc_id 
     ) 
     unpivot (rn for review_type in (admsn_reviewed_rn as 'ADMSN', 
      disch_reviewed_rn as 'DISCH')) 
    ) 
    where rn = 1 
    and (abs(reviewed_time - admsn_time) <= 1 
     or abs(reviewed_time - disch_time) <= 1) 
) 
pivot (min(reviewed_time) as review_time, min(user_id) as reviewer 
for review_type in ('ADMSN' as admsn, 'DISCH' as disch)) 
/

其中給出:

ENC_ID ADMSN_TIME   ADMSN_REVIEW_TIME ADMSN_ DISCH_TIME   DISCH_REVIEW_TIME DISCH_ 
---------- ------------------- ------------------- ------ ------------------- ------------------- ------ 
    16755387 03/19/0013 11:10:00 03/19/0013 13:02:00 FOOBAR 03/22/0013 12:55:00 03/22/0013 08:35:00 FOOBAR 
0

你的基本的問題是如何找到T時間以後第一次受到約束。從這裏開始,

SELECT E.ENC_ID, 
     E.ADMSN_TIME, 
     min(REVIEWED_TIME) as ADMSN_REVIEWED_TIME, 
FROM ENCOUNTER as E 
JOIN PROBLEM_LIST as P 
ON  E.ENC_ID = P.ENC_ID 
AND  ADMSN_TIME < REVIEWED_TIME 
AND  REVIEWED_TIME <= ADMSN_TIME + 1 
GROUP BY E.ENC_ID, E.ADMSN_TIME 

加入到其他任何你需要的東西。

相關問題