有一个像这样的SQL表:
+----+-----------+----------+
| ID | Comment | ParentID |
+----+-----------+----------+
| 1 | Some Text | 0 |
| 2 | Some Text | 0 |
| 3 | Some Text | 2 |
| 4 | Some Text | 2 |
| 5 | Some Text | 3 |
| 6 | Some Text | 3 |
| 7 | Some Text | 1 |
+----+-----------+----------+
这是博客文章和一些儿童评论的评论。孩子级别的深度是无限的:每个孩子评论都可以有另一个孩子评论。
用户想要删除ID为2的父级注释。所以我需要一个SQL查询,它选择所有的子注释ID(以及子子注释等)。
目前我有这个查询,它只选择子评论的第一级:
SELECT ID
FROM comment_table
WHERE ParentID = 2
是否可以在一个查询中选择所有那些儿童评论?
答案 0 :(得分:1)
这是一个常见的问题,并且鉴于您的数据库结构并没有真正的答案,因为大多数SQL数据库不支持递归查询,因此您需要执行许多查询(这很糟糕)或限制嵌套(也很糟糕)。
有解决方案,但它们涉及备用数据库模式。 Bill Karwin已经写了很多关于PHP / MySQL中分层数据问题的文章。他在这里有一个演讲:http://www.percona.tv/percona-webinars/models-for-hierarchical-data-in-sql-and-php他在那里讨论了一些选择。他还在他的书(SQL Antipatterns)中写了一篇关于不同选项及其优缺点的博客和书面章节。缺点
答案 1 :(得分:1)
您可以使用简单的递归函数在PHP中执行此操作:
function child_comments($id,&$arr) {
$sql = 'SELECT ID, Comment, ParentID FROM comment_table WHERE ParentID='.$id;
// get rows for $sql
foreach ($rows as $row) {
$arr[] = $row;
child_comments($row['id'],$arr);
}
}
child_comments(2,$comments);
$comments
会有一系列评论2的孩子,这是孩子的孩子等等......
上面的代码应该被视为伪代码,并且需要调整以适应从数据库中检索数据的方式(pdo,mysqli,mysql _ *)。
特别是// get rows for $sql
需要替换相关代码来获取$sql
中保存的语句的行。
对child_comments
的递归调用可能还需要根据从数据库返回的行的结构进行调整,$row['id']
可能不是访问ID
字段的正确方法。
答案 2 :(得分:1)
我喜欢使用的这个问题的一个解决方案是添加“物化路径”。
您只需要添加一个包含对象整个祖先的列。例如,您的表格调整如下:
+----+-----------+----------+----------+
| ID | Comment | ParentID | TreePath |
+----+-----------+----------+----------+
| 1 | Some Text | 0 | |
| 2 | Some Text | 0 | |
| 3 | Some Text | 2 | -2-|
| 4 | Some Text | 2 | -2-|
| 5 | Some Text | 3 | -2-3-|
| 6 | Some Text | 3 | -2-3-|
| 7 | Some Text | 1 | -1-|
+----+-----------+----------+----------+
选择2的所有后代如下所示:
SELECT ID FROM comment_table WHERE TreePath LIKE '-2-%'
如果你想在PHP中构建一个评论树,你甚至可以按TreePath
排序,以获得一个很容易转换为树的数组。
答案 3 :(得分:0)
我不知道单个查询,但是如何在该表中添加isChildren列?
这样你就会收到要删除的评论的ID,将其存储在$ idToDelete中并删除id等于你收到的id的评论,删除它,将其parentId保存在$ idToDelete中等。 你可以在一段时间内做到这一点,检查列isChildren是否正确。如果isChildren为false,则删除该注释的第一个父项及其所有子项。
应该不应该工作吗? Dunno如果修改数据库是一个选择。