SQL选择一行的后代

标签 sql sqlite recursion recursive-query

假设一个树结构在 SQL 中是这样实现的:

CREATE TABLE nodes (
    id INTEGER PRIMARY KEY,
    parent INTEGER -- references nodes(id)
);

尽管可以在此表示中创建循环,但我们假设我们永远不会让这种情况发生。该表将仅存储根(父为空的记录)及其后代的集合。

目标是,给定表中一个节点的 id,找到它的所有后代节点。

AB 的后代,如果 A 的父代是 BA 的父级是 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 的(直接) child :

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 的 child 、孙子和曾孙:

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 数据库中完成。

最佳答案

一些数据库允许使用递归公用表表达式,但 SQLite 不允许。

您可以考虑更改表定义。使用这样的表,很容易查询 1 的所有后代:

id (varchar)
--------------
001
001002
001002003
001002003004
001002003005
001002006

这允许您查询 1 的所有后代,例如:

SELECT * FROM YourTable WHERE id LIKE '001%'

这听起来有点古怪,但在实践中效果很好。

关于SQL选择一行的后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2742242/

相关文章:

c - 递归使用C语言

mysql - SQL查询SP从11个表获取数据并避免笛卡尔输出

mysql - 表充满数据后添加检查约束

sqlite - 使用rust 柴油 : SQLite INSERT RETURNING multiple ids

android.database.sqlite.SQLiteException : near "ON": syntax error (code 1)

sql - 防止触发器相互递归执行?

sql - 为什么 hibernate hql distinct 会导致 sql 在左连接中不同?

mysql - 存储两个单词的最佳数据类型?

sql - SQL-删除多个条目

java - 递归替换为 Java 正则表达式?