How can i get rif of theses subqueries ?
(all tables have columns Created and LastEdited as timestamps)
table Process
- ID
- Title
table ProcessHistory
- ID
- ProcessID
- HistoryID
table History
- ID
- Title (new, open, closed etc.)
When i try to get a list of processes with cols of the last status title i do:
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
When i try to get a list filtered by a specific status (Where the latest HistoryID is 1 - "all open Processes")
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
For performance reasons i want to get rid of theses subqueries? How can i replace the subquery?
Thanks in advance !
Query you posted not give proper result as per ORDER BY ProcessHistory.ID DESC LIMIT 1
Try below query as per result of your query
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;
Here the sql fiddle:
sql fiddle link
If you want other result then comment.
由于实际的子查询用于获取与每个“进程”相关的“最后”行,因此您既不能将其转换为JOIN,也不能将其用作设置会话变量的单独查询。
You'll still need to make another select to filter out the rest of the process history, but you should use a derived table instead of a subquery, like this 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
As Himanshu Patel pointed out, your query to "get a list filtered by a specific status (Where the latest HistoryID is 1 - "all open Processes")" will not produce the desired effect. It will simply return all processes that have a HistoryID of 1. See this sqlfiddle .
Instead, you want to use a derived table to get those latest process history ids, join them with the processes, and filter on the history ids like this sqlfiddle :
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
An alternative approach would be to create a view that filters the ProcessHistory table to the latest history per process and join on that. YMMV, but in some cases, performance can be improved that way.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.