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进行分组,但违反直觉,我们没有按最近的活动排序我们的论坛主题,相关的论坛响应不是最新的.
这里出了什么问题?有没有办法改变这个查询,以便我得到最近贡献的论坛主题的列表,以及他们各自最近的评论?
第二个查询的问题是您正在执行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)
对于功能更强大的数据库,可以使用窗口函数(也称为分析函数)来编写此代码。然后您可以避免这些连接之一。在 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)