【发布时间】:2014-04-18 14:57:39
【问题描述】:
我一直在逐步测试我最近开发的公告板。我在我的 SQL 查询中遇到了一个小错误。
SELECT `user`.avatar, `user`.username, `user`.id AS user_id, `post`.title,
`post`.id, `post`.date AS post_date, `comment`.date AS last_comment_date
FROM `post`
INNER JOIN `user` ON `post`.user_id = `user`.id
LEFT JOIN `comment` ON `post`.id = `comment`.post_id
WHERE `post`.category_id = 1
ORDER BY IFNULL(`last_comment_date`, `post_date`) DESC;
会产生类似的东西;
我碰巧知道这是什么原因。 MySQL 将所有 cmets 与其 post 连接起来,换句话说,它是一对多的关系,一个 post 可以有多个 cmets。这会产生分页问题,因为前十个帖子可能相同,具体取决于它是否有十个 cmets。我碰巧只需要comment 表中的最新评论日期。
我遇到了几个解决方案。
按
post.id分组,但在行分组后不能按顺序执行。检索整个结果集并通过 PHP 对我需要的内容进行排序。使用这种方法,我的性能可能会受到很大影响。
执行多个查询,但这不是个好主意。
执行子查询,但我不知道这是否是一种不好的做法。
最好的做法是什么?如果是一对多关系,是否有办法阻止 MySQL 在连接中返回重复数据?
编辑 1
正如@Zane 所问,这个 SQL 查询...
SELECT `user`.avatar, `user`.username, `user`.id AS user_id, `post`.title, `post`.id,
`post`.date AS post_date, MAX(`comment`.date)
FROM `post`
INNER JOIN `user` ON `post`.user_id = `user`.id
LEFT JOIN `comment` ON `post`.id = `comment`.post_id
WHERE `post`.category_id = 1
GROUP BY `post`.id
ORDER BY IFNULL(MAX(`comment`.date), `post_date`) DESC
产生;
这似乎正是我想要的。如果帖子有 cmets (或发布日期),则帖子将按最新评论日期排序。我也可以将它与分页 LIMITS 一起使用,而无需任何预处理。我还需要IFNULL 吗?我想是的。
EDiT 2
还有一个缺陷。如果帖子的 last_comment_date 为 NULL,则无法正确排序。如果你参考下图。你可以看到 last_comment_date 就在那里,即使应该发生了碰撞。
请忽略下面的内容。
编辑 3
这就是我想要的。
【问题讨论】:
-
我知道这并不能直接解决您的问题,但为了将来参考,请勿使用保留名称,如
user作为列名。 -
您是否尝试过使用
MAX()作为评论日期,然后使用Group by其他列? -
+1 啊谢谢您的评论!我没有意识到这是一个保留关键字。 D:这就是为什么我打字时它的颜色编码。不管是否需要,我都计划稍微修改一下结构。
-
@Zane 你确定
user是保留关键字吗? -
@Zane 请参考我上面的编辑。你是这样的意思吗?我还需要ifnull吗?我想我会的,因为不是每个帖子都会有评论,谢谢!我也相信阿比克。当我在 SQL 编辑器中输入它时,它会用颜色编码。
标签: php mysql sql join duplicates