MySQL,Group By OrderBy

时间:2012-02-21 23:29:41

标签: 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));

场景:

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

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

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

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

  

按队名虚拟订购!这么简单的问题。 (这个答案将获得约+4票)

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

1 个答案:

答案 0 :(得分: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.

变化:

  • LEFT JOIN media自身 每个team_uidGROUP BY变量),以及M.time < M2.time(变量)我们想要MAX。)。
  • 因为它是LEFT JOIN,如果有一个M.time,其中没有更大的 M2.time(对于同一个团队),则M2.time将为NULL。这正是当M.time是该团队的最长时间时。
  • M2.time IS NULL条件中添加WHERE(以强制执行上述操作)
  • 删除GROUP BYORDER BY(在加入条件中处理)。