簡體   English   中英

如何用聯接替換子查詢?

[英]How to replace sub-query by joins?

如何獲得這些子查詢的內容?

(所有表的列Created和LastEdited作為時間戳)

table Process
 - ID
 - Title

table ProcessHistory
 - ID
 - ProcessID
 - HistoryID

table History
 - ID
 - Title (new, open, closed etc.) 

當我嘗試獲取帶有最后一個狀態標題的cols的進程列表時,我會這樣做:

SELECT DISTINCT Process.*, History.Title AS HistoryTitle, History.ID AS HistoryID
FROM `Process`
LEFT JOIN ProcessHistory AS ProcessHistory ON Process.ID=ProcessHistory.ProcessID
LEFT JOIN History AS History ON HistoryID=ProcessHistory.HistoryID
WHERE History.ID = (
    SELECT HistoryID FROM ProcessHistory 
    WHERE ProcessID=Process.ID 
    ORDER BY ProcessHistory.ID DESC LIMIT 1
)
GROUP BY Process.ID
ORDER BY Process.ID DESC LIMIT 0, 100

當我嘗試獲取按特定狀態過濾的列表時(最新的HistoryID為1-“所有打開的進程”)

SELECT DISTINCT Process.*, History.Title AS HistoryTitle, History.ID AS HistoryID
FROM `Process`
LEFT JOIN ProcessHistory AS ProcessHistory ON Process.ID=ProcessHistory.ProcessID
LEFT JOIN History AS History ON HistoryID=ProcessHistory.HistoryID
WHERE History.ID=(
    SELECT HistoryID FROM ProcessHistory 
    WHERE HistoryID =1   
    AND ProcessID=Process.ID ORDER BY ProcessHistory.ID DESC LIMIT 1
)
GROUP BY Process.ID
ORDER BY Process.ID DESC LIMIT 0, 100

出於性能原因,我想擺脫這些子查詢? 如何替換子查詢?

提前致謝 !

您發布的查詢未按照ORDER BY ProcessHistory.ID DESC LIMIT 1提供正確的結果

根據查詢結果嘗試以下查詢

 SELECT DISTINCT p.*, h.Title AS HistoryTitle,h.ID AS  HistoryID
FROM
Process p JOIN ProcessHistory ph ON p.ID=ph.ProcessID and ph.HistoryID=1 
JOIN History h ON h.ID=ph.HistoryID
GROUP BY p.ID
ORDER BY p.ID DESC LIMIT 0, 100;

這里的SQL小提琴:
sql小提琴鏈接

如果您想要其他結果,請發表評論。

SELECT *
FROM Process AS p
LEFT JOIN (
  SELECT ph.ProcessID, ph.HistoryID, h.Title AS HistoryTitle
  FROM ProcessHistory AS ph
  JOIN History AS h ON ph.HistoryID = h.ID
  WHERE h.ID = 1
) AS phh ON p.ID = phh.ProcessID
ORDER BY p.ID DESC LIMIT 100

屏幕截圖

由於實際的子查詢用於獲取與每個“進程”相關的“最后”行,因此您既不能將其轉換為JOIN,也不能將其用作設置會話變量的單獨查詢。

您仍然需要進行另一個選擇以過濾掉其余的過程歷史記錄,但是您應該使用派生表而不是子查詢,例如sqlfiddle

SELECT Process.*, History.Title AS HistoryTitle
FROM Process
JOIN (
  SELECT ProcessID, max(HistoryID) as HistoryID
  FROM ProcessHistory
  GROUP BY ProcessID
) PH ON PH.ProcessID = Process.ID
JOIN History ON History.ID = PH.HistoryID
ORDER BY Process.ID DESC LIMIT 0, 100

正如Himanshu Patel指出的那樣,您的查詢“獲取按特定狀態過濾的列表(最新的HistoryID為1-“所有打開的進程”)將無法產生預期的效果。 它只會返回所有HistoryID為1的進程。請參見此sqlfiddle

相反,您希望使用派生表來獲取這些最新的進程歷史記錄ID,將它們與進程一起加入,並過濾諸如sqlfiddle這樣的歷史記錄ID:

SELECT DISTINCT Process.*, History.Title AS HistoryTitle
FROM Process
JOIN (
  SELECT ProcessID, max(HistoryID) as HistoryID
  FROM ProcessHistory
  GROUP BY ProcessID
) PH ON PH.ProcessID = Process.ID
JOIN History ON History.ID = PH.HistoryID
WHERE PH.HistoryID = 1
ORDER BY Process.ID DESC LIMIT 0, 100

一種替代方法是創建一個視圖,該視圖將ProcessHistory表篩選為每個進程的最新歷史記錄,然后加入該視圖。 YMMV,但在某些情況下,可以通過這種方式提高性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM