2016-07-15 77 views
0

我怎样才能得到这些子查询的rif?如何用联接替换子查询?

(所有表都列上创建和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 

由于性能原因,我想摆脱这些子查询? 我如何替换子查询?

在此先感谢!

+0

由您创建和加载的sqlfiddle将帮助我们帮助您。注意:加载并不意味着完全加载。这可能意味着每个表格有5到10行数据。 – Drew

+0

这里的sql小提琴: http://sqlfiddle.com/#!9/3d9001/1 – derRobert

+0

它真的是性能瓶颈还是这是不成熟的,甚至可能是非优化的优化? – e4c5

回答

0

您仍然需要再作选择滤除历史过程的其余部分,但你应该使用derived table,而不是一个子查询,这样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帕特尔指出, ,“查询按特定状态筛选的列表(最新的HistoryID为1 - ”所有打开的进程“)”的查询不会产生所需的效果。它将简单地返回历史ID为1的所有进程。请参阅此sqlfiddle

相反,你要使用派生表来获得这些最新的工艺历史的ID,用流程加入他们,和历史上的ID过滤这样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 

另一种方法是创建一个视图,将ProcessHistory表过滤到每个进程的最新历史记录并加入。 YMMV,但在某些情况下,可以通过这种方式改善性能。

3

查询您张贴不给正确的结果为每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 fiddle link

如果希望其他结果然后评论。

0
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 

Screenshot

0

由于实际子查询,用于获取有关每一个“过程”,“最后”行,你既不能把它转换为连接,也可以使用它作为一个单独的查询设置一个会话变量。