您可能会问的第一个问题是 SO 上有多少 Group by/Order by 问题?很多。这些都不适合我的具体情况。这是我的以下 SQL 查询。
目标是在 $teamArr
(一组唯一 ID)中获取每个团队的最新媒体。
我面临的问题是,它不会为每个人获取最新的媒体,而是基于组的顺序,即独立于团队的媒体时间。
这是 MySQL 命令(使用 PHP 的 sprintf()
命令,以便于使用团队 ID)。
sprintf("SELECT M.*, T.name, T.has_image
FROM media AS M
JOIN teams AS T
ON T.team_uid = M.team_uid
WHERE M.team_uid IN (%s)
GROUP BY T.team_uid
ORDER BY M.time DESC", implode(", ", $teamArr));
场景:
A 队有 3 小时前的媒体项目,B 队有 6 小时前和 2 天前的 2 个项目,C 队有 9 小时前的媒体项目。
如果选择的顺序是团队 A、C、B,则媒体项将如下...
- TeamA 3 小时前的媒体项目
- TeamC 的 9 小时前媒体项目
- TeamB 2 天前的媒体项目
可能会有一些傻话说
Just order by team name dummy! Such a simple problem. (this answer will get about +4 votes)
但这显然对我一点帮助都没有。我不知道哪些团队会有最佳顺序(如果任何自然或不自然的顺序甚至适用于超过 3 个案例)。有没有一种方法可以在 1 个 SQL 查询中完成。我听说循环中的 MySQL 是一个糟糕的决定,因此我希望它在 1 个 SQL 调用中工作。
最佳答案
这种查询通常被标记为“greatest-n-per-group”以供将来引用。
您想要每个团队的最长时间和相应的列,对吗?
解决这个问题的典型方法是 LEFT JOIN
您想要获取最大值的表(在您的情况下为 media
):
SELECT M.*, T.name, T.has_image
FROM media AS M
LEFT JOIN media AS M2 -- new: join media to itself
ON M.team_uid = M2.team_uid -- within each team_uid (GROUP BY var)
AND M.time < M2.time -- and a sort on time (ORDER BY var)
JOIN teams AS T -- same as before.
ON T.team_uid = M.team_uid
WHERE M.team_uid IN (%s)
AND M2.time IS NULL -- new: this selects the MAX M.time for each team.
变化:
-
LEFT JOIN
media
对自身在每个team_uid
(GROUP BY
变量),这样M.time < M2.time
(我们想要 MAX 的变量)。 - 因为它是
LEFT JOIN
,如果有一个 M.time 没有更大的 M2.time(对于同一个团队),则 M2.time 将为 NULL。这正是 M.time 是该团队的 MAX 时间。 - 添加
M2.time IS NULL
在WHERE
条件(执行上述) - 删除
GROUP BY
,ORDER BY
(在连接条件中处理)。
关于php - MySQL,按顺序分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9386961/