我只想弄清楚如何将以下查询序列优化为单个查询。
具体来说,下面的查询就像在用户登录帐户时向用户显示的警报。
$sq = "SELECT COUNT(*) as totm FROM login as l
JOIN msgs m on m.id = l.id
WHERE m.tstamp > l.mtstamp AND l.id = $id;";
$sq .= "SELECT COUNT(*) as totp FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 0 AND u.id = $id;";
$sq .= "SELECT COUNT(*) as totq FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 1 AND u.id = $id";
现在我使用mysqli_multi_query()
来运行这多个查询。
但是我已经设法将其缩减为单个查询
$sq = "SELECT m.totm,p.totp FROM login as l
JOIN info as u on u.id = l.id
LEFT JOIN (SELECT tstamp,id,COUNT(*) as 'totm' FROM msgs GROUP BY id) m
ON m.id = l.id AND m.tstamp > l.mtstamp
LEFT JOIN (SELECT tstamp,cid,type,id,COUNT(*) as 'totp' FROM pst
GROUP BY id) p
ON p.cid = u.cid AND p.tstamp > l.ptstamp AND p.type = 0
AND p.id <> l.id WHERE l.id = $id
LEFT JOIN (SELECT tstamp,cid,type,id,COUNT(*) as 'totp' FROM pst
GROUP BY id) p
ON p.cid = u.cid AND p.tstamp > l.ptstamp AND p.type = 1
AND p.id <> l.id WHERE l.id = $id LIMIT 1";
当我使用EXPLAIN STATEMENT
尝试单个查询时,查询输出太差,很多行都会受到影响。
当我在三个查询中单独执行相同操作时,结果很好。我不确定我应该运行多个查询还是尝试单个查询。
在谷歌搜索后,我发现groupBY会导致连接和许多行的严重开销。好的,任何人都让我知道什么是更好的方法来解决这个问题。任何人都可以帮我写一个更优化的查询。谢谢。任何帮助是极大的赞赏。
答案 0 :(得分:1)
如果您尝试检索特定ID的计数,那么我建议您将查询组合为select中的子查询。使用GROUP BY
没有任何意义,因为您正在查找特定ID的计数。
SELECT
(SELECT COUNT(*) FROM login as l
JOIN msgs m on m.id = l.id
WHERE m.tstamp > l.mtstamp AND l.id = $id) totm,
(SELECT COUNT(*) FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 0 AND u.id = $id) totp,
(SELECT COUNT(*) FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 1 AND u.id = $id) totq
将此与检索每个ID的计数进行对比,在这种情况下,GROUP BY
上的id
会很有用:
SELECT t1.id,t1.totm,t2.totp,t3.totq
FROM
(SELECT l.id, COUNT(*) as totm FROM login as l
JOIN msgs m on m.id = l.id
WHERE m.tstamp > l.mtstamp
GROUP BY l.id) t1
LEFT JOIN (SELECT u.id, COUNT(*) as totp FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 0
GROUP BY u.id) t2 ON t1.id = t2.id
LEFT JOIN (SELECT u.id, COUNT(*) as totq FROM info as u
JOIN pst as p on p.cid = u.cid
JOIN login as l on l.id = u.id
WHERE p.tstamp > l.ptstamp AND p.id <> u.id
AND p.type = 1
GROUP BY u.id) t3 ON t2.id = t3.id