相关问题:MySQL "Group By" and "Order By"
我可以使用以下查询来检索某项的下载列表:
SELECT items.id, items.name, users.fullName AS downloadedBy, dl.dateTime AS lastDownload
FROM items
LEFT OUTER JOIN downloads dl ON dl.itemID = items.id
LEFT JOIN users ON users.id = dl.userID
WHERE items.id = '47'
ORDER BY dl.dateTime DESC
这与预期的一样,返回下载列表,其中最新的位于顶部。
我想做的是检索该项目的上次下载和下载总数。
此查询:
SELECT items.id, items.name, users.fullName AS downloadedBy, dl.dateTime AS lastDownload, COUNT(dl.id) AS total
FROM items
LEFT OUTER JOIN downloads dl ON dl.itemID = items.id
LEFT JOIN users ON users.id = dl.userID
WHERE items.id = '47'
ORDER BY dl.dateTime DESC
GROUP BY items.id
返回正确的总数,但是下载详细信息(用户名和日期)是列表中间的随机条目。如链接问题中所述,将主查询包装在子查询中,然后将GROUP BY放在后面,具有相同的效果。是否可以在一个查询中同时检索上次下载和总数?
我使用的MySQL版本5.7.21禁用了ONLY_FULL_GROUP_BY
。
[编辑] 回答Ankit的评论:
第一个查询的输出:
id | name | downloadedBy | lastDownload ============================================== 47 | Item 47 | Matilda | 2018-08-18 19:10 47 | Item 47 | Marmaduke | 2018-08-14 07:21 47 | Item 47 | Simon | 2018-06-11 14:02 47 | Item 47 | Boris | 2018-06-11 14:00
所需的输出:
id | name | downloadedBy | lastDownload | total ====================================================== 47 | Item 47 | Matilda | 2018-08-18 19:10 | 4
第二个查询的实际输出:
id | name | downloadedBy | lastDownload | total ====================================================== 47 | Item 47 | Simon | 2018-06-11 14:02 | 4
答案 0 :(得分:0)
您要查询的是具有独立逻辑的两个独立的事物。上一次下载查询一行,而行数计算的是行数,与上一次下载查询无关。
查询不起作用的原因是,聚合函数是根据每个常规列(id,name,fullName和dateTime)计算的。如果您未禁用ONLY_FULL_GROUP_BY,则将获得每个组合的计数。既然您已经做完了,MySQL将从这些结果集中选择随机值。禁用ONLY_FULL_GROUP_BY通常是一件坏事。它可以保护您避免错误使用GROUP BY。
要进行查询,您可以对感兴趣的两件事分别进行查询,然后将它们组合为一个。
select max(id), max(name), max(downloadedBy), max(lastDownload), max(cnt)
from (
(SELECT items.id, items.name, users.fullName AS downloadedBy, dl.dateTime AS lastDownload
FROM items
LEFT OUTER JOIN downloads dl ON dl.itemID = items.id
LEFT JOIN users ON users.id = dl.userID
WHERE items.id = '47'
ORDER BY dl.dateTime DESC
limit 1)
union
(select null, null, null, null, count(*)
FROM items
LEFT OUTER JOIN downloads dl ON dl.itemID = items.id
LEFT JOIN users ON users.id = dl.userID
WHERE items.id = '47')
) q;