2015-10-20 172 views
2

我有一個放射性肺結節事件的放射學報告數據庫。每名患者都有一個醫療記錄號,每個程序都有一個唯一的登錄號。因此,MRN可以爲不同的程序提供多個登錄號。登記號碼是遞增的,所以如果患者有多個登錄號碼,最大的登錄號碼是最新的程序。我需要:SQL中的相關子查詢

  • 找出最老的(最初的)研究
  • 查找該inital
  • 後談到最快的一次研究,計算各區間

我相信這個問題之間的時間差可以使用相關的子查詢來解決。但是,我還沒有足夠的SQL來解決這個問題。我試過自己加入表格並找到每個子查詢的最大加入。下面的一些示例代碼來製作數據集:

CREATE TABLE Stack_Example (Rank, Accession1, MRN1, Textbox2, Textbox47,Textbox43,Textbox45,ReadBy,SignedBy,Addendum1,ReadDate,SignedDate,Textbox49,Result,Impression,max_size_nodule, max_nodule_loc, max_nodule_type) 


    INSERT INTO Stack_Example 
VALUES ("10", "33399", "001734", "5/21/1965", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "COMB, YAHAIR", "YES", "12/19/2014 11:48", "12/19/2014 17:50", "TEXT", "Results of Nodules!","Impressions of Nodules","3.0", "right middle lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("9", "33104", "001734", "5/21/1965", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "12/21/2013 06:52", "01/21/2014 06:52", "TEXT", "Results of Nodules!","Impressions of Nodules","3.7", "right upper lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("9", "33374", "001734", "5/21/1965", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "01/21/2014 08:19", "01/21/2014 06:52", "TEXT", "Results of Nodules!","Impressions of Nodules","2.1", "right lower lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("1", "34453", "001734", "5/21/1965", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "03/14/2014 09:14", "03/14/2014 09:14", "TEXT", "Results of Nodules!","Impressions of Nodules","1.4", "left upper lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("1", "27122", "80592", "1/14/1984", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "06/26/2013 10:20", "06/26/2013 10:20", "TEXT", "Results of Nodules!","Impressions of Nodules","2.5", "left upper lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("1", "27248", "80592", "1/14/1984", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "08/01/2013 06:23", "08/01/2013 06:23", "TEXT", "Results of Nodules!","Impressions of Nodules","4.0", "left lower lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("1", "28153", "35681", "03/01/1990", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "09/14/2012 05:00", "09/14/2012 05:00", "TEXT", "Results of Nodules!","Impressions of Nodules","4.0", "left lower lobe","None Found") 

INSERT INTO Stack_Example 
VALUES ("1", "29007", "35681", "03/01/1990", "CTS", "3341", "ROUTINE", "TUCK, YOURPANTSIN", "PICK, YASELFUP", "YES", "11/16/2012 08:23", "11/16/2012 08:23", "TEXT", "Results of Nodules!","Impressions of Nodules","3.5", "right lower lobe","None Found") 

顯然這是假數據。我一直在試圖做的是用相關的子查詢自己加入表格。像這樣:

SELECT DISTINCT a.Accession1, a.MRN1, a.ReadDate, p.Accession1, p.ReadDate 
FROM Stack_Example as a 
INNER JOIN Stack_Example as p on a.MRN1 = p.MRN1 
WHERE a.Accession1 = 
(SELECT max(Accession1) 
FROM Stack_Example as b 
WHERE a.MRN1 = b.MRN1 AND 
a.Accession1 != p. Accession1) 
ORDER BY a.MRN1 

理想是什麼,我想是一個MRN對行和加入每位患者每個MRN爲列(日期爲種質等一起)主表。這樣的事情:

| MRN  | Accession (First Follow-up) | Date First Followup |Accession (Second Follow-up)..| Date Second Follow up | etc. 
|:-----------|----------------------------:|:-------------------:| 
| 001734  |  33374     | ......  
| 80592  |  27248     | ......  

我相信子查詢我需要一系列左連接;不過,有沒有更好的方法來做到這一點?有些患者隨訪7次以上。感謝任何幫助,對於長時間的解釋感到抱歉。希望格式可以。

+0

你也可以包括工作www.SqlFiddle.com,這樣纔有利於測試的答案。 –

回答

1

你在正確的軌道上。你可以使用自連接和子查詢來完成。該表應該與MRN1上的自身結合,並且後一記錄的登錄1等於該MRN1的最小登錄1大於第一個記錄(下一個MRN1)的MRN1。左連接允許查詢報告所有記錄,甚至最後一個(沒有後繼者)。

這個查詢產生的所有對相鄰的研究:

Select a.ReadDate ARead, b.ReadDate BRead, 
     b.ReadDate-A.ReadDate elapsed, 
     a.*, b.*, 
From table a 
    left Join table b 
     on b.MRN1 = a.MRN1 
      and b.Accession1 = 
       (Select min(Accession1) From table 
       where MRN1 = a.MRN1 
        and Accession1 > a.Accession1) 

此查詢生成前三研究:

Select a.ReadDate ARead, b.ReadDate BRead, c.ReadDate CRead, 
     b.ReadDate-A.ReadDate elapsedAB, 
     c.ReadDate-b.ReadDate elapsedBCB 
From table a 
    left Join table b 
     on b.MRN1 = a.MRN1 
      and b.Accession1 = 
       (Select min(Accession1) From table 
       where MRN1 = a.MRN1 
        and Accession1 > a.Accession1) 
    left Join table c 
     on c.MRN1 = a.MRN1 
      and c.Accession1 = 
       (Select min(Accession1) From table 
       where MRN1 = a.MRN1 
        and Accession1 > b.Accession1) 
Where A.ReadDate = 
     (Select Min(readDate) from table 
     where MRN1 = a.MRN1) 
+0

嗨,查爾斯,謝謝你的回覆。你的代碼有效;但是,我希望MRN不會在行之間重複。相反,我希望將MRNs放在一行中,並將每個後續列作爲列。在當前的代碼中,如果一個人有4項研究,他們將在4個不同的行上。我試圖在第一列中使用第一個(最老的研究)的一行MRN,並且每個研究在附加列中向右。謝謝。 –

+0

@david,這很難,它需要查詢動態生成每行輸出不同數量的列。 –

0

不知道,如果你希望所有的範圍或僅僅是第2位。查爾斯查詢我相信提供所有。

這只是前兩個。

SELECT * 
FROM  YourTable as O -- oldest 
LEFT JOIN YourTable as neO -- next oldest 
     ON O.MRN1 = neO.MRN1 
WHERE 
     O.Accession1 = (SELECT MIN(Accession1) 
         FROM YourTable A 
         WHERE A.MRN1 = O.MRN1) 

    AND neO.Accession1 = (SELECT MIN(Accession1) 
         FROM YourTable A 
         WHERE A.MRN1 = O.MRN1 
          AND A.Accession1 <> O.Accession1) 
+0

嗨胡安,你的例子適用於第一次後續研究。但是,如何添加更多的左連接以進行更多的後續操作?這段代碼正是我第一次跟進所需要的,一行是MRN,最老的先行,然後是下一行。我想將每個後續行動增加到7左右。 –

+0

因此,您希望Charles和我的合併還是Charles查詢的改進?你看過http://www.sqlfiddle.com/了嗎?我嘗試上傳你的樣本,但得到了錯誤sintaxis,沒有時間修復它 –

+0

確實。添加這樣的: 'AND neO2.Accession1 =(SELECT MIN(Accession1) FROM Four_mm_or_Less甲 WHERE A.MRN1 = O.MRN1 AND A.Accession1 <> O.Accession1 \t \t \t \t \t \t和A. Accession1 <> neO.Accession1)' 到腳本的最後一個代碼會將其展開到下一個後續步驟,但不包括所有未進行2次跟進的情況。我試圖仍然保留那些沒有後續的MRN,但是沒有後續的字段只有空值。 –

0

你可能想發表minimal working example,你的例子包括不需要的,使事情變得複雜很多列。

以下架構位於SQL Fiddle上,請參閱下文。我將Accession 34453的年份更改爲2015,加入順序和日期錯誤。

CREATE TABLE Stack_Example (
    Accession  VARCHAR(32), 
    MRN    VARCHAR(32), 
    ReadDate   DATETIME 
); 

INSERT INTO Stack_Example 
VALUES ("33399", "001734", STR_TO_DATE("12/19/2014 11:48", "%m/%d/%Y %h:%i")), 
     ("33104", "001734", STR_TO_DATE("12/21/2013 06:52", "%m/%d/%Y %h:%i")), 
     ("33374", "001734", STR_TO_DATE("01/21/2014 08:19", "%m/%d/%Y %h:%i")), 
     ("34453", "001734", STR_TO_DATE("03/14/2015 09:14", "%m/%d/%Y %h:%i")), 
     ("27122", "80592", STR_TO_DATE("06/26/2013 10:20", "%m/%d/%Y %h:%i")), 
     ("27248", "80592", STR_TO_DATE("08/01/2013 06:23", "%m/%d/%Y %h:%i")), 
     ("28153", "35681", STR_TO_DATE("09/14/2012 05:00", "%m/%d/%Y %h:%i")), 
     ("29007", "35681", STR_TO_DATE("11/16/2012 08:23", "%m/%d/%Y %h:%i")); 

集團的毗連歷屆之加入
看來你想有一個可變的列數,或動態創建這些列。據我所知,這是行不通的。正如其他答案中提出的,您必須爲每列添加LEFT JOIN。但是,在MySQL中,您可以使用GROUP_CONCAT來連接組的值。您的值不再位於單個列中,但結果可能接近您的預期。

接下來生成兩個後續日期之間的差異,在PostgreSQL中你有窗口函數來實現這一點。在MySQL中,您可以使用nested sets or adjacent lists

SELECT S.MRN, 
     GROUP_CONCAT('Acc: ', S.Accession, 
        ' Date: ', S.ReadDate, 
        ' Days to prev.: ', IFNULL(Diff, 0) 
        ORDER BY Accession SEPARATOR ' :: ') 
FROM (
    SELECT S0.MRN, 
     S0.Accession, 
     S0.ReadDate, 
     TIMESTAMPDIFF(DAY, S1.ReadDate, S0.ReadDate) AS Diff 
    FROM stack_example S0 
    -- join on previous accession 
    LEFT JOIN stack_example S1 
    ON S1.MRN = S0.MRN 
    AND S1.Accession = (SELECT MAX(S2.Accession) 
         FROM stack_example S2 
         WHERE S2.MRN = S0.MRN 
          AND S2.Accession < S0.Accession) 
) S 
GROUP BY MRN; 

可能接近你正在尋找什麼,Results SQL小提琴。

| MRN | Result                                                        | 
|--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 
| 001734 | Acc: 33104 Date: 2013-12-21 06:52:00 Days to prev.: 0 :: Acc: 33374 Date: 2014-01-21 08:19:00 Days to prev.: 31 :: Acc: 33399 Date: 2014-12-19 11:48:00 Days to prev.: 332 :: Acc: 34453 Date: 2015-03-14 09:14:00 Days to prev.: 84 | 
| 35681 | Acc: 28153 Date: 2012-09-14 05:00:00 Days to prev.: 0 :: Acc: 29007 Date: 2012-11-16 08:23:00 Days to prev.: 63                              | 
| 80592 | Acc: 27122 Date: 2013-06-26 10:20:00 Days to prev.: 0 :: Acc: 27248 Date: 2013-08-01 06:23:00 Days to prev.: 35                              | 

加入固定上加入的人數
下面的查詢是相同的查詢查爾斯BRETANA已經發布了。它加入了固定數量的種質。這個查詢的缺點是,你沒有得到最近的加入者,而是七/四個最古老的加入者。

SELECT S0.MRN, 
     S0.Accession, S0.ReadDate, 
     0, 
     S1.Accession, S1.ReadDate, 
     TIMESTAMPDIFF(DAY, S0.ReadDate, S1.ReadDate), 
     S2.Accession, S2.ReadDate, 
     TIMESTAMPDIFF(DAY, S1.ReadDate, S2.ReadDate), 
     S3.Accession, S3.ReadDate, 
     TIMESTAMPDIFF(DAY, S2.ReadDate, S3.ReadDate) 

FROM stack_example S0 
LEFT JOIN stack_example S1 
    ON S1.MRN = S0.MRN 
AND S1.Accession = (SELECT MIN(SX.Accession) 
         FROM stack_example SX 
         WHERE SX.MRN = S0.MRN 
         AND SX.Accession > S0.Accession) 
LEFT JOIN stack_example S2 
    ON S2.MRN = S0.MRN 
AND S2.Accession = (SELECT MIN(SX.Accession) 
         FROM stack_example SX 
         WHERE SX.MRN = S1.MRN 
         AND SX.Accession > S1.Accession) 
LEFT JOIN stack_example S3 
    ON S3.MRN = S0.MRN 
AND S3.Accession = (SELECT MIN(SX.Accession) 
         FROM stack_example SX 
         WHERE SX.MRN = S2.MRN 
         AND SX.Accession > S2.Accession) 

WHERE S0.Accession = (SELECT MIN(SX.Accession) 
         FROM stack_example SX 
         WHERE SX.MRN = S0.MRN) 
; 

結果

| MRN | Accession |     ReadDate | 0 | Accession |     ReadDate | TIMESTAMPDIFF | Accession |     ReadDate | TIMESTAMPDIFF | Accession |    ReadDate | TIMESTAMPDIFF | 
|--------|-----------|-----------------------------|---|-----------|----------------------------|---------------|-----------|----------------------------|---------------|-----------|-------------------------|---------------| 
| 001734 |  33104 | December, 21 2013 06:52:00 | 0 |  33374 | January, 21 2014 08:19:00 |   31 |  33399 | December, 19 2014 11:48:00 |   332 |  34453 | March, 14 2015 09:14:00 |   84 | 
| 80592 |  27122 |  June, 26 2013 10:20:00 | 0 |  27248 | August, 01 2013 06:23:00 |   35 | (null) |      (null) |  (null) | (null) |     (null) |  (null) | 
| 35681 |  28153 | September, 14 2012 05:00:00 | 0 |  29007 | November, 16 2012 08:23:00 |   63 | (null) |      (null) |  (null) | (null) |     (null) |  (null) |