有幾種方法可以在單個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。
什麼是錯誤? – jcjr
@jcjr我通過提及錯誤更新了我的問題 – Arif
在子查詢中,您按照patient_id進行分組。由於有很多patient_id,它會返回多行 –