【问题标题】:MySQL query for sorting comments and their nested replies用于排序评论及其嵌套回复的 MySQL 查询
【发布时间】:2011-08-17 23:19:09
【问题描述】:

我已经在这里和其他地方阅读了 10 多篇相关帖子,但仍然无法弄清楚这一点,因为我对 php 和 MySQL 还很陌生:

我正在使用 WordPress 并尝试在旧主题中实现嵌套 cmets。我的表已设置完毕(我们称其为“cmets”)并具有以下字段:

comment_ID | comment_date | comment_parent, etc.

comment_parent 在顶级 cmets 中保持 等于 0;它等于嵌套回复中回复的评论的 comment_ID

原始的 MySQL 查询如下所示:

SELECT * FROM $wpdb->comments 
WHERE comment_post_ID = %d AND comment_approved = '1' 
ORDER BY comment_date ASC LIMIT %d"

通过跟随并输出评论列表的php,cmets按日期列出,不考虑嵌套回复:

comment_ID | comment_date | comment_parent
100          Jan 01         0      (this is a top level comment)
104          Jan 03         0      (this is a top level comment)
106          Jan 04         100    (this is a reply to the first comment)
108          Jan 05         104    (this is a reply to the second comment)

显然,由于我是按日期排序的,所以顺序被破坏了。评论 106 应该出现在评论 100 的正下方,评论 108 应该出现在评论 104 的下方。

我正在尝试不更改我的 php,我想使用 MySQL 查询来执行此操作,但无法正确处理。我曾尝试按照类似问题中的建议使用 JOIN、GROUP BY、HAVING,但没有任何成功。有没有办法让我从查询中实现正确的排序并保持我的 php 完整?

【问题讨论】:

  • 您好!欢迎来到 SO!即使您确实创建了这样的查询,您不会得到重复的内容吗?直到“嵌套评论”列的所有列都将包含相同的数据。然后,您必须编写代码来“忽略”前面的列”。您可能想尝试查看 Fowler 的“依赖映射”模式 - 它不会在 MySQL 中使用,可能需要在代码中处理。
  • 您可以先一次性获取所有顶级 cmets,然后在第二轮中获取嵌套的 cmets(全部)并相应地填充您的内容。或者根据上述内容编写一些重要的代码以使其正确。 AFAIK 可能无法在不重复内容的情况下进行查询。我也想知道这个问题的解决方案,到目前为止我就是这样处理的!
  • 我在使用 JOIN 时曾想知道重复内容的问题,但由于我一开始无法让它工作,所以我从来没有找到答案。我曾希望我可以编写一个足够扭曲的查询,以便简单地对我的行进行排序而不重复......我会研究相关映射,谢谢!
  • 这个:link 是最接近我在这里找到的解决方案,但无法让它工作,给我语法错误

标签: mysql sorting comments nested


【解决方案1】:

好吧,我终于弄明白了,部分感谢 Nupul 在上面的评论,他说:“您可以先一次性获取所有顶级 cmets,然后在第二轮中获取嵌套的 cmets(全部)并填充你的内容相应地。”。我确实尝试过这个选项没有成功,但这激励了我坚持下去......

为了记录并希望这可以帮助将来的人,这是我修复它的方法。 两个单独的 MySQL 查询首先获取 顶级 cmets,然后获取 嵌套评论回复(这些查询的格式适用于 WordPress。)

$comments = $wpdb->get_results($wpdb->prepare("
  SELECT * 
  FROM $wpdb->comments 
  WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_parent = '0' 
  ORDER BY comment_date ASC 
  LIMIT %d
",etc,etc)); 

$replies = $wpdb->get_results($wpdb->prepare("
  SELECT * 
  FROM $wpdb->comments 
  WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_parent <> '0' 
  ORDER BY comment_date ASC 
  LIMIT %d
",etc,etc));

然后我进入我的主评论循环 (FOREACH),只寻找 顶级 cmets。在那个循环中,在底部,我跳入一个嵌套的 IF 循环,寻找嵌套的 cmets

$reply->comment_parent == $comment->comment_ID(比较我的 2 个 MySQL 查询)

如果为 true,则将 $cmets 调整为等于 $replies 以便我的嵌套 cmets 被 WordPress 正确回显。然后我将 $cmets 的值返回到其原始值,并退出我的嵌套注释循环回到主 FOREACH。

我的推理或执行可能存在缺陷,但它就像一个魅力!当然,这并没有提供额外的嵌套级别,所有嵌套的 cmets 都是一个接一个地写入,即使它们是相互回复的,但这对我来说已经足够了!

对于演示,http://www.vincentmounier.com/blog2/ 并单击帖子底部的任何“显示评论”链接。 Nupul,再次感谢您的鼓励!

【讨论】:

  • 很高兴知道它有效。现在它确实...查找相关映射并将您的解决方案与它进行比较。它会像魅力一样匹配:)
  • 基于我的假设,即一个新概念的实现头痛程度与查找有关它的信息的难度成比例地上升,依赖映射可能是要走的路,但是男孩,它会伤害!我只是在网上看了一会儿就放弃了;对我来说太混乱或太先进了。不过谢谢你的建议! :)
  • 我知道这已经过时了,但我希望任何查看此内容的人都知道,简单地运行两个单独的查询并不是一个很好的答案。至少你可以做一个UNION 而不是两个单独的查询。性能和效率为王,运行多个查询对于大多数问题来说是一个非常糟糕的解决方案。在此示例中,您甚至不需要执行两个查询。这绝对是浪费。
【解决方案2】:

你最好改变你的桌子设计。实现嵌套 cmets 的更好方法之一是使用 Modified Preorder Tree Traversal (MPTT)

This is an article about an MPTT menu,但您应该能够学习如何使用类似的方案来实现评论系统。

【讨论】:

  • 是的,我在其他地方读过这篇文章,但决定反对它,不想重写我的 WordPress 数据库——那个旧主题不值得。我会在弄乱数据库之前更改主题...
  • 更具体地说,Wordpress 已经支持嵌套 cmets,但我正在向主题添加内联评论显示,并且必须绕过常规评论显示系统并实时执行我的 MySQL 查询...
猜你喜欢
  • 2013-03-10
  • 1970-01-01
  • 2011-07-05
  • 2013-06-20
  • 2021-07-24
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多