如何在 GROUP BY 之前订购此数据库 [重复]

Posted

技术标签:

【中文标题】如何在 GROUP BY 之前订购此数据库 [重复]【英文标题】:How can I get this database to order before the GROUP BY [duplicate] 【发布时间】:2013-04-25 17:32:01 【问题描述】:

我创建了一个高尔夫记分卡网站。我正在处理的页面是玩家资料。当您访问球员资料时,它会按上次玩的顺序 (DESC) 显示每门课程。除了,由于下面的 ORDER BY 命令,最后播放的顺序是混乱的。相反,当它 GROUP 时,它会采用最早的日期,而不是最近的日期。

分组完成后,它会按顺序正确显示它们(DESC)...只是由于课程按 date_of_game ASC 而不是 DESC 分组而导致的顺序错误。希望这不会太令人困惑..谢谢。

$query_patrol321 = "SELECT t1.*,t2.* FROM games t1 LEFT JOIN scorecards t2 ON t1.game_id=t2.game_id WHERE t2.player_id='$player_id' GROUP BY t1.course_id ORDER BY t1.date_of_game DESC";
$result_patrol321 = mysql_query($query_patrol321) or die ("<br /><br />There's an error in the MySQL-query: ".mysql_error());
while ($row_patrol321 = mysql_fetch_array($result_patrol321)) 
    $player_id_rank = $row_patrol321["player_id"];
    $course_id = $row_patrol321["course_id"];
    $game_id = $row_patrol321["game_id"];
    $top_score = $row_patrol321["total_score"];

【问题讨论】:

我没有完全理解这个问题,但你能尝试将排序更改为ORDER BY MAX(t1.date_of_game) DESC吗?如果您尝试显示每门课程的最后播放日期,这将起作用。 完美,谢谢。很高兴这是一个如此简单的修复。我想不通。 Please, don't use mysql_* functions in new code。它们不再维护and are officially deprecated。看到red box?改为了解 prepared statements,并使用 PDO 或 MySQLi - this article 将帮助您决定哪个。 【参考方案1】:

尝试从查询中删除 GROUP BY 子句。只有在 SELECT 中同时具有普通列和聚合函数(min、max、sum、avg、count)时,才应该使用 GROUP BY。你只有普通的列。

【讨论】:

+1, GROUP BY 没有聚合是对 SQL 的滥用。 MySQL 允许这种行为。我一直觉得这很奇怪和令人困惑。我相信没有聚合它需要聚合中的第一个条目。 虽然 MySQL 确实不会在没有聚合函数 + 普通列的情况下使用 GROUP BY 引发错误,但您确实不应该以这种方式使用它。总有正确的查询方式。【参考方案2】:

它以ASC 顺序显示分组结果的事实是巧合,因为这是它们的插入顺序。与 MS SQL Server 等其他 RDBMS 相比,MySQL 允许您将非聚合列添加到 GROUPed 查询。这种非标准行为会造成您所看到的混乱。如果这不是 MySQL,您需要为给定分组的所有选定列定义聚合。

MySQL 的行为是(我相信)将与GROUP 匹配的第一行用于非聚合列。我建议不要这样做。

即使你在聚合,你也不是 ORDERing 聚合列。

所以你想做的是ORDER BYMAX日期DESC

这样,您将按每门课程的最晚日期(您的分组标准)进行排序。

SELECT 
    t1.* -- It would be better if you actually listed the aggregations you wanted
    ,t2.* -- Which columns do you really want?
FROM 
    games t1 
LEFT JOIN 
    scorecards t2 
        ON t2.[game_id] =t1[.game_id]
WHERE 
    t2.[player_id]='$player_id' 
GROUP BY 
    t1.[course_id] 
ORDER BY 
    MAX(t1.[date_of_game]) DESC

【讨论】:

【参考方案3】:

如果您想要最大日期,则插入逻辑来获取它。不要依赖于列的顺序或未记录的 MySQL 特性。当值不相同时,MySQL 明确不鼓励在 group by 中使用非聚合列:

MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.  (see [here][1])

你如何做你想做的事?以下查询查找每门课程的最新日期并仅使用该日期 -- 而不是 group by

SELECT t1.*, t2.*
FROM games t1 LEFT JOIN
     scorecards t2
     ON t1.game_id=t2.game_id
WHERE t2.player_id='$player_id' and
      t1.date_of_game in (select MAX(date_of_game)
                          from games g join
                               scorecards ss
                               on g.game_id = ss.game_id and
                                  ss.player_id = '$player_id'
                          where t1.course_id = g.course_id
                         )
GROUP BY t1.course_id
ORDER BY t1.date_of_game DESC

如果game_id 是自动递增的,您可以使用它来代替date_of_game。如果两场比赛可以在同一日期在同一球场进行,这一点尤其重要。

【讨论】:

以上是关于如何在 GROUP BY 之前订购此数据库 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Group by 不能正确处理订单

如何使用 Group By 对数据库表进行分组

如何在表格中模拟SQL group by?

使用 CTE 在 Group by 之前或之后过滤

MySQL GROUP BY 返回第一项 - 需要选择最后一项

如何使用 group by 和 order by LINQ DataTable 以删除重复数据