MySQL,GroupBy OrderBy

Mic*_*ael 4 php mysql group-by sql-order-by greatest-n-per-group

您可能会问的第一个问题是,SO上有多少Group by/Order by Questions?很多.这些都不符合我的具体情况.这是我的以下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));
Run Code Online (Sandbox Code Playgroud)

场景:

A队有一个3小时前的媒体项目,B队有2个项目6小时前和2天前,而C队有一个9小时前的媒体项目.

如果选择的顺序结果是团队A,C,B那么媒体项目将如下...

  • TeamA的3小时前媒体项目
  • TeamC的9小时前媒体项目
  • TeamB的2天前媒体项目

可能会有一些愚蠢的评论说

只需按团队名称命名!这么简单的问题.(这个答案将获得约+4票)

但这显然对我毫无帮助.我不知道哪些团队会有最佳订单(如果有任何自然或不自然的订单甚至可以使用超过3个案例).有没有这样的方法,我可以在1个SQL查询中执行此操作.我听说循环中的MySQL是一个糟糕的决定,因此我希望它在1个SQL调用中工作.

mat*_*fee 6

这种查询通常被标记为"每组最大n个"以供将来参考.

你想要每个团队的最大时间相应的列,对吗?

解决这个问题的典型方法是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.
Run Code Online (Sandbox Code Playgroud)

变化:

  • LEFT JOIN media以自身之内的每个team_uid(的GROUP BY变量),并且使得M.time < M2.time(变量,我们希望的MAX).
  • 因为它是a LEFT JOIN,如果有一个M.time,没有更大的 M2.time(对于同一个团队),则M2.time将为NULL.这恰恰是M.time是该团队的最长时间.
  • 添加M2.time IS NULLWHERE条件(执行上述)
  • 删除GROUP BY,ORDER BY(在连接条件中处理).