没有子查询的最新数据分组

Latest data group-by without a subquery

这是一个很常见的情况,但我不确定我是否做错了什么。

TABLE POSTS [ ID, USER_ID, TOPIC_ID, TIME ]

我只想获得每个用户在 topic_id '1'

上的最后一个 post
SELECT p.*
FROM
  posts p,
  (
    SELECT   user_id, max(time) mtime
    FROM     posts
    WHERE    topic_id = 1
    GROUP BY user_id
  ) pm
WHERE
  p.user_id = pm.user_id AND
  p.time    = pm.mtime

这是正确的吗?没有子查询有没有办法做到这一点?

是否可以通过 spring 数据查询获取此数据,或者这只是一个 JDBC/stored 过程?

要在没有子查询的情况下执行此操作,请使用 HAVING

SELECT   user_id, topic_id,  time
FROM     posts
WHERE    topic_id = 1
GROUP BY user_id
HAVING time = max(time)

您可以为每个用户 获取最新的 post,而无需 使用子查询,方法是使用 join:

SELECT p.* 
FROM posts p
LEFT OUTER JOIN posts t
ON(p.user_id = t.user_id and p.time < t.time and t.topic_id = 1)
WHERE p.topic_id = 1 and t.topic_id is null

我不确定如何避免sub-query,但另一种方法是

SELECT p.*
FROM   posts p
WHERE  p.time = (SELECT Max(time) mtime
                 FROM   posts pm
                 WHERE  pm.topic_id = 1
                        AND p.user_id = pm.user_id) 

Window 函数 Row_number 在这种情况下会非常有用 不幸的是 Mysql 不支持

另一个避免子查询的解决方案(但同样可能不会那么快)是使用 substring_index 按时间降序排列您想要最新的每个字段,然后使用 SUBSTRING_INDEX只需获取 SUBSTRING_INDEX.

返回的第一个条目
SELECT user_id, 
    SUBSTRING_INDEX(GROUP_CONCAT(`id` ORDER BY `time` DESC), ',', 1),
    SUBSTRING_INDEX(GROUP_CONCAT(`topic_id` ORDER BY `time` DESC), ',', 1),
    SUBSTRING_INDEX(GROUP_CONCAT(`time` ORDER BY `time` DESC), ',', 1)
FROM posts
WHERE    topic_id = 1
GROUP BY user_id