在连接表上使用group by时忽略排序

时间:2015-02-18 17:42:11

标签: mysql sql

我正在尝试编写1个查询来显示按最新发布日期排序的论坛帖子列表。

这是从数据库获取数据的一个非常简单的过程,但是由于joinsgroup by,我想要使用的order by是不可能的。

表结构

ForumRooms

|  id  |  title  |
|----------------|
|  1   | Room 1  |
|  2   | Room 2  |

ForumThreads

|  id  |  title    |  forum_room_id  |
|------------------|-----------------|
|  1   | Thread 1  |  1              |
|  2   | Thread 2  |  2              |
|  3   | Thread 3  |  1              |

ForumPosts

|  id  |  content  |  forum_thread_id |  post_time  |  user_id  |
|------------------|------------------|-------------|-----------|
|  1   | A post 1  |  1               |  15/02/2015 |  1        |
|  2   | A post 2  |  2               |  16/02/2015 |  2        |
|  3   | A post 3  |  1               |  17/02/2015 |  1        |
|  4   | A post 4  |  1               |  18/02/2015 |  2        |
|  5   | A post 5  |  2               |  19/02/2015 |  1        |


期望输出

这是我理想的输出,线程按最新的帖子帖子排序。

|  Thread Title |  Last Post User  | Last Post Time  |  Creator User  |
|---------------|------------------|-----------------|----------------| 
|  Thread 2     |  1               |  19/02/2015     |  2             |
|  Thread 1     |  2               |  18/02/2015     |  1             |


问题

目前,我可以在1个查询中获取所有内容但是在尝试ORDER BY ForumPosts.id时出现问题,我认为这是由于GROUP BY加入了联接。

这意味着我拥有所有必需的数据,但它不是最新论坛帖子的顺序。

当前不正确的查询

SELECT 
  ForumThreads.title, 
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id ASC), ',', 1),
  MAX(ForumPosts.`post_time`),
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id DESC), ',', 1)
FROM
  forumThreads 
  INNER JOIN `ForumRooms` 
    ON ForumThreads.forum_room_id = ForumRooms.id 
  INNER JOIN `ForumPosts` 
    ON ForumThreads.id = ForumPosts.`forum_thread_id` 
WHERE ForumRooms.id = 1 
GROUP BY ForumThreads.id 
ORDER BY ForumPosts.id DESC

如何编写能够实现上述所需输出的查询?


更新1

我已经尝试按照 Jean-FrançoisSavard的建议实现子查询方法,但ORDER BY a.id被忽略,它仍按ForumTopics.id排序

3 个答案:

答案 0 :(得分:1)

您可以使用子查询

select * from(
SELECT 
  ForumPosts.id,
  group_concat(ForumThreads.title), 
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id ASC), ',', 1),
  MAX(ForumPosts.`post_time`),
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id DESC), ',', 1)
FROM
  forumThreads 
  INNER JOIN `ForumRooms` 
    ON ForumThreads.forum_room_id = ForumRooms.id 
  INNER JOIN `ForumPosts` 
    ON ForumThreads.id = ForumPosts.`forum_thread_id` 
WHERE ForumRooms.id = 1 
GROUP BY ForumThreads.id) a
ORDER BY a.id DESC

答案 1 :(得分:1)

您可以使用:

SELECT a.ThreadTitle, a.LastPostUser, a.LastPostTime, p2.user_id CreatorUser FROM (
    SELECT t.title ThreadTitle, p.user_id LastPostUser, p.post_time LastPostTime, p.forum_thread_id
    FROM (SELECT * FROM ForumPosts ORDER BY post_time DESC) p
    JOIN ForumThreads t ON t.id=p.forum_thread_id
    JOIN ForumRooms r ON t.forum_room_id=r.id
    GROUP BY threadTitle ) a
JOIN (SELECT * FROM ForumPosts GROUP BY forum_thread_id) p2 ON p2.forum_thread_id=a.forum_thread_id 
ORDER BY 3 DESC

答案 2 :(得分:1)

只需对原始查询进行少量更改 - 将MAX(ForumPosts.id) AS max_post_id添加到SELECT中,然后按顺序进行排序:

SELECT 
  ForumThreads.title, 
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id ASC), ',', 1),
  MAX(ForumPosts.`post_time`),
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id DESC), ',', 1),
  MAX(ForumPosts.id) AS max_post_id
FROM
  forumThreads 
  INNER JOIN `ForumRooms` 
    ON ForumThreads.forum_room_id = ForumRooms.id 
  INNER JOIN `ForumPosts` 
    ON ForumThreads.id = ForumPosts.`forum_thread_id` 
WHERE ForumRooms.id = 1 
GROUP BY ForumThreads.id 
ORDER BY max_post_id DESC

或者你可以别名MAX(ForumPosts.post_time)并按顺序排序:

SELECT 
  ForumThreads.title, 
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id ASC), ',', 1),
  MAX(ForumPosts.`post_time`) AS max_post_time,
  SUBSTRING_INDEX(GROUP_CONCAT(ForumPosts.user_id ORDER BY ForumPosts.id DESC), ',', 1)
FROM
  forumThreads 
  INNER JOIN `ForumRooms` 
    ON ForumThreads.forum_room_id = ForumRooms.id 
  INNER JOIN `ForumPosts` 
    ON ForumThreads.id = ForumPosts.`forum_thread_id` 
WHERE ForumRooms.id = 1 
GROUP BY ForumThreads.id 
ORDER BY max_post_time DESC