假设在SQL中实现树结构,如下所示:
CREATE TABLE nodes (
id INTEGER PRIMARY KEY,
parent INTEGER -- references nodes(id)
);
虽然可以在此表示中创建循环,但我们假设我们永远不会让这种情况发生。该表只存储一个根集合(父节点为空的记录)及其后代。
目标是,给定表中节点的id,找到作为其后代的所有节点。
A 是 B 的后代,如果 A 的父级是 B 或 A 的父母是 B 的后代。注意递归定义。
以下是一些示例数据:
INSERT INTO nodes VALUES (1, NULL);
INSERT INTO nodes VALUES (2, 1);
INSERT INTO nodes VALUES (3, 2);
INSERT INTO nodes VALUES (4, 3);
INSERT INTO nodes VALUES (5, 3);
INSERT INTO nodes VALUES (6, 2);
代表:
1
`-- 2
|-- 3
| |-- 4
| `-- 5
|
`-- 6
我们可以通过以下方式选择1
的(直系)子项:
SELECT a.* FROM nodes AS a WHERE parent=1;
我们可以通过以下方式选择1
的子孙:
SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id;
我们可以通过以下方式选择1
的子孙,孙子孙女:
SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id
UNION ALL
SELECT c.* FROM nodes AS a, nodes AS b, nodes AS c WHERE a.parent=1 AND b.parent=a.id AND c.parent=b.id;
如何构造查询以获取节点1
的所有后代而不是固定深度的后代?看起来我需要创建一个递归查询或其他东西。
我想知道使用SQLite是否可以进行这样的查询。但是,如果这种类型的查询需要SQLite中没有的功能,我很想知道它是否可以在其他SQL数据库中完成。
答案 0 :(得分:8)
某些数据库允许使用递归公用表表达式,但不能使用SQLLite。
您可以考虑更改表格定义。使用这样的表格,可以轻松查询1:
的所有后代id (varchar)
--------------
001
001002
001002003
001002003004
001002003005
001002006
这允许您查询1的所有后代,如:
select * from YourTable where id like '001%'
这听起来有点蠢,但在实践中效果很好。
答案 1 :(得分:6)
您设置架构的方式并不能很好地适应关系模型(正如您所发现的那样)。但是另一种方式起初可能并不那么明显,但更灵活。它被称为“嵌套集模型”,它只是稍微不同地构建了一些东西。
Managing Hierarchical Data in MySQL(查看“嵌套集模型”部分)显示了如何在MySQL中执行此操作,但它应该很容易转换为SQLite。我不会在这里详细介绍,因为那篇文章实际上很长,但它应该能为你提供所需的一切。
答案 2 :(得分:1)
Oracle有一个可用于此的CONNECT BY语法,但当然它特定于oracle。