MySQL分组不尊重ORDER BY

cai*_*lin 6 mysql sql sorting group-by

我正在尝试执行MySQL查询以在Web论坛中查找最近活动的线程(以及每个线程的最新注释).线程存储在两个表中,forum_topics并且forum_responses每个表forum_topic都有很多forum_responses.

在这里,我对forum_reponses加入的搜索进行了搜索forum_topics,降序排序为forum_response.id:

select t.id, t.title, r.id, r.body 
    from forum_responses r 
    inner join forum_topics t on (r.forum_topic_id = t.id) 
    order by r.id desc;

+----+--------------+----+----------------------------------+
| id | title        | id | body                             |
+----+--------------+----+----------------------------------+
| 17 | New Topic    | 69 | yes                              |
| 19 | Test Topic 1 | 68 | This is a test                   |
| 17 | New Topic    | 64 | hey yo                           |
| 19 | Test Topic 1 | 63 | Test Topic Starter               |
| 18 | Test Topic   | 62 | Test.                            |
| 18 | Test Topic   | 61 | Test                             |
| 17 | New Topic    | 60 | Another test response.           |
| 17 | New Topic    | 59 | Test response.                   |
| 17 | New Topic    | 54 | What should this topic be about? |
+----+--------------+----+----------------------------------+
Run Code Online (Sandbox Code Playgroud)

好的,到目前为止一切顺利.但它正在返回重复 - 我只想拥有最近回复的论坛主题.所以我在我的查询中添加了一个GROUP BY,因此我们可以按主题ID进行分组:

select t.id, t.title, r.id, r.body 
    from forum_responses r 
    inner join forum_topics t on (r.forum_topic_id = t.id) 
    group by t.id 
    order by r.id desc;

+----+--------------+----+----------------------------------+
| id | title        | id | body                             |
+----+--------------+----+----------------------------------+
| 19 | Test Topic 1 | 63 | Test Topic Starter               |
| 18 | Test Topic   | 61 | Test                             |
| 17 | New Topic    | 54 | What should this topic be about? |
+----+--------------+----+----------------------------------+
Run Code Online (Sandbox Code Playgroud)

但现在,我们遇到了一个问题:它是按论坛主题ID进行分组,但违反直觉,我们没有按最近的活动排序我们的论坛主题,相关的论坛响应不是最新的.

这里出了什么问题?有没有办法改变这个查询,以便我得到最近贡献的论坛主题的列表,以及他们各自最近的评论?

200*_*ess 0

诊断

第二个查询的问题是您正在执行GROUP BY t.id,但选择的其他列(t.title、r.id和r.body)不是聚合函数。事实上,这是标准 SQL 下的错误,但 MySQL 不会抱怨,除非您启用服务器范围的ONLY_FULL_GROUP_BY设置。相反,MySQL 只提供不确定的结果。

建议的解决方案

select t.id, t.title, r.id, r.body
    from (
            select forum_topic_id, max(id) as id
                from forum_responses
                group by forum_topic_id
        ) as latest
        inner join forum_topics t on latest.forum_topic_id = t.id
        inner join forum_responses r on latest.id = r.id
    order by r.id desc;
Run Code Online (Sandbox Code Playgroud)

超越MySQL

对于功能更强大的数据库,可以使用窗口函数(也称为分析函数)来编写此代码。然后您可以避免这些连接之一。在 PostgreSQL、MS SQL Server 或 Oracle 上,查询看起来更像这样:

select t.id, t.title, r.id, r.body
    from (
        select forum_topic_id, id, body
            from forum_responses
            where 1 = rank(id over partition by forum_topic_id order by id desc)
        ) as r
        inner join forum_topics t on t.id = r.forum_topic_id
    order by r.id desc;
Run Code Online (Sandbox Code Playgroud)