表:
(`post_id`, `forum_id`, `topic_id`, `post_time`)
(79, 8, 4, '2012-11-19 06:58:08');
(80, 3, 3, '2012-11-19 06:58:42'),
(81, 9, 9, '2012-11-19 06:59:04'),
(82, 11, 6, '2012-11-19 16:05:39'),
(83, 9, 9, '2012-11-19 16:07:46'),
(84, 9, 11, '2012-11-19 16:09:33'),
查询:
SELECT post_id, forum_id, topic_id FROM posts
GROUP BY topic_id
ORDER BY post_time DESC
LIMIT 5
结果:
[0] => [post_id] => 84 [forum_id] => 9 [topic_id] => 11
[1] => [post_id] => 82 [forum_id] => 11 [topic_id] => 6
[2] => [post_id] => 81 [forum_id] => 9 [topic_id] => 9
[3] => [post_id] => 80 [forum_id] => 3 [topic_id] => 3
[4] => [post_id] => 79 [forum_id] => 8 [topic_id] => 4
问题:
如何重写查询以便返回post_id - > 83而不是post_id - > 81?
他们都有相同的论坛和主题ID,但是post_id - > 81的日期早于post_id - > 83.
但似乎Group By获得了“第一”记录,而不是“最新”记录。
我尝试将查询更改为
SELECT post_id, forum_id, topic_id, MAX(post_time)
但是返回post_id 81和83
答案 0 :(得分:26)
如果选择未在group子句中使用但未聚合的属性,则结果未指定。 I.e 您不知道从哪个行中选择其他属性。 (sql标准不允许这样的查询,但MySQL更放松)。
然后应该写入查询,例如如
SELECT post_id, forum_id, topic_id
FROM posts p
WHERE post_time =
(SELECT max(post_time) FROM posts p2
WHERE p2.topic_id = p.topic_id
AND p2.forum_id = p.forum_id)
GROUP BY forum_id, topic_id, post_id
ORDER BY post_time DESC
LIMIT 5;
或
SELECT post_id, forum_id, topic_id FROM posts
NATURAL JOIN
(SELECT forum_id, topic_id, max(post_time) AS post_time
FROM posts
GROUP BY forum_id, topic_id) p
ORDER BY post_time
LIMIT 5;
答案 1 :(得分:5)
尝试类似
的内容SELECT post_id, forum_id, topic_id
FROM (SELECT post_id, forum_id, topic_id
FROM posts
ORDER BY post_time DESC)
GROUP BY topic_id
ORDER BY topic_id desc
LIMIT 0,5
根据需要更改order by
和limit
。
答案 2 :(得分:0)
也许不是最好的方法,但有时函数 group_concat()可以是userfull,它将返回一个所有聚合值的字符串,按照你想要的方式排序并用逗号分隔(耦合值是由空间隔开)。然后我使用函数SPLIT_STRING()来剪切字符串中的第一个id。
SELECT
post_id,
SPLIT_STRING( group_concat( forum_id, post_time ORDER BY post_time DESC ) ,' ',1 )as forum_id,
SPLIT_STRING( group_concat( topic_id, post_time ORDER BY post_time DESC ) ,' ',1 )as topic_id ,
FROM posts
GROUP BY topic_id
ORDER BY post_time DESC
LIMIT 5
所以聚合的forum_id,post_time将是这样的:
81 2012-11-19 06:59:04,83 2012-11-19 16:07:46
所以你需要使用整数和日期时间对的字符串表示,每个情侣用逗号分隔,所以我用这个函数得到第一个INT:
CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1),
delim, '');
注意:函数SPLIT_STRING(str,delim,pos)在这里找到:Equivalent of explode() to work with strings in MySQL
答案 3 :(得分:0)
这也适合你。
SELECT *
FROM (
SELECT post_id, forum_id, topic_id FROM posts
ORDER BY post_time DESC
LIMIT 5
) customeTable
GROUP BY topic_id