2012-12-24 47 views
0

我有一個表tbl_patient,我想獲取每位患者的最後2次訪問,以便比較患者病情是否正在改善或降級。從GROUP BY獲取MySql DB的2nd Higest值

tbl_patient 

id | patient_ID | visit_ID | patient_result 
1 |  1  | 1  |  5 
2 |  2  | 1  |  6 
3 |  2  | 3  |  7 
4 |  1  | 2  |  3 
5 |  2  | 3  |  2 
6 |  1  | 3  |  9 

我想下面的查詢來獲取每個病人爲最後一次訪問,

SELECT MAX(id), patient_result FROM `tbl_patient` GROUP BY `patient_ID` 

現在我想取得與查詢每個病人的第二個最後一次訪問,但它給我的錯誤 (#1242 - 子查詢返回多個1行)

SELECT id, patient_result FROM `tbl_patient` WHERE id <(SELECT MAX(id) FROM `tbl_patient` GROUP BY `patient_ID`) GROUP BY `patient_ID` 

如果我錯了

+0

什麼是錯誤? – jcjr

+0

@jcjr我通過提及錯誤更新了我的問題 – Arif

+0

在子查詢中,您按照patient_id進行分組。由於有很多patient_id,它會返回多行 –

回答

4
select p1.patient_id, p2.maxid id1, max(p1.id) id2 
from tbl_patient p1 
join (select patient_id, max(id) maxid 
     from tbl_patient 
     group by patient_id) p2 
on p1.patient_id = p2.patient_id and p1.id < p2.maxid 
group by p1.patient_id 

id11是最後一次訪問的ID,id2是2到上次訪問的ID。

+0

它獲取第一個患者的上次訪問和第二個患者的第一次訪問 – Arif

+0

向外部查詢添加了缺少的GROUP BY子句。 – Barmar

+0

謝謝親愛的,用這個來解決我的問題 –

-1

爲什麼不乾脆用...

GROUP BY `patient_ID` DESC LIMIT 2 

...和做下一步的休息嗎?

+3

這限制了結果2總行,而不是每個病人2。 – Barmar

1
SELECT id, patient_result FROM `tbl_patient` t1 
JOIN (SELECT MAX(id) as max, patient_ID FROM `tbl_patient` GROUP BY `patient_ID`) t2 
     ON t1.patient_ID = t2.patient_ID 
WHERE id <max GROUP BY t1.`patient_ID` 
+0

它只是獲取每個患者的第一次訪問 – Arif

0

試試這個..

SELECT id, patient_result FROM tbl_patient AS tp WHERE id < ((SELECT MAX(id) FROM tbl_patient AS tp_max WHERE tp_max.patient_ID = tp.patient_ID) - 1) GROUP BY patient_ID 
2

你的第一個查詢沒有得到最後的訪問,因爲它給出的結果5和6而不是2和9 你可以試試這個查詢:

SELECT patient_ID,visit_ID,patient_result 
FROM tbl_patient 
where id in (
    select max(id) 
    from tbl_patient 
    GROUP BY patient_ID) 
union 
SELECT patient_ID,visit_ID,patient_result 
FROM tbl_patient 
where id in (
    select max(id) 
    from tbl_patient 
    where id not in (
     select max(id) 
     from tbl_patient 
     GROUP BY patient_ID) 
    GROUP BY patient_ID) 
order by 1,2 
1

有幾種方法可以在單個SQL語句中返回指定的結果集。

不幸的是,大多數這些方法產生相當笨拙的陳述。

更優雅的前瞻性陳述傾向於在處理大型設置時性能很差(或難以忍受)。而傾向於有更好表現的陳述則更加不雅觀。

三個最常見的方法利用:

  • 相關子查詢
  • 不平等加入(近笛卡爾乘積)
  • 兩個超過數據

這裏有一個方法使用兩遍遍歷數據,使用MySQL用戶變量,這基本上模擬了分析RANK() OVER(PARTITION ...)樂趣ction在其他DBMS提供:


SELECT t.id 
    , t.patient_id 
    , t.visit_id 
    , t.patient_result 
    FROM (
     SELECT p.id 
       , p.patient_id 
       , p.visit_id 
       , p.patient_result 
       , @rn := if(@prev_patient_id = patient_id, @rn + 1, 1) AS rn 
       , @prev_patient_id := patient_id AS prev_patient_id 
      FROM tbl_patients p 
      JOIN (SELECT @rn := 0, @prev_patient_id := NULL) i 
      ORDER BY p.patient_id DESC, p.id DESC 
     ) t 
WHERE t.rn <= 2 

注意,這涉及到一個內嵌視圖,這意味着有將是一個傳過來的表中創建一個「派生表D」中的所有數據。然後,外部查詢將對派生表運行。所以,這基本上是兩遍數據。

通過消除內聯視圖返回的patient_id列的重複值,可以稍微調整此查詢以提高性能。但是我如上所示顯示它,所以我們可以更好地理解正在發生的事情。

這種方法在大型設備上可能相當昂貴,但通常比其他一些方法更加高效。

還要注意,如果該患者僅存在一個id值,則該查詢將返回一行patient_id;它不會限制返回到至少有兩行的患者。


它也可能得到同等的結果集與相關子查詢

SELECT t.id 
    , t.patient_id 
    , t.visit_id 
    , t.patient_result 
    FROM tbl_patients t 
WHERE (SELECT COUNT(1) AS cnt 
      FROM tbl_patients p 
      WHERE p.patient_id = t.patient_id 
      AND p.id >= t.id 
     ) <= 2 
ORDER BY t.patient_id ASC, t.id ASC 

注意,這是利用「從屬子查詢」中,這基本上意味着返回的每個行從t,MySQL正在有效地運行對數據庫的另一個查詢。所以,這對於大型遊戲機而言將會非常昂貴(以時間爲條件)。


作爲另一種方法,如果有相對較少的id值每一個病人,你也許可以用不平等獲得通過聯接

SELECT t.id 
    , t.patient_id 
    , t.visit_id 
    , t.patient_result 
    FROM tbl_patients t 
    LEFT 
    JOIN tbl_patients p 
    ON p.patient_id = t.patient_id 
    AND t.id < p.id 
GROUP 
    BY t.id 
    , t.patient_id 
    , t.visit_id 
    , t.patient_result 
HAVING COUNT(1) <= 2 

注意,這將創造一個近每個患者的笛卡爾產品。對於每個患者的有限數量的id值,這不會太糟糕。但是,如果患者具有數百個值,則中間結果可能很大,大約爲(O)n ** 2。