sql - 按递归深度有限的前任排序
问题描述
我有一个这样的链接列表
LineID PredecessorLineID SuccessorLineID
----------- ----------------- ---------------
3 NULL 2
2 3 815
815 2 1
1 815 195
195 1 52
我需要以一种没有 Predecessor 的行首先出现的方式进行排序,然后是第一行作为前任的行,依此类推
我可以用这个查询对其进行排序
WITH q ([LineID], PredecessorLineID, SuccessorLineID, init, lvl) AS
(
SELECT [LineID], [PredecessorLineID], [SuccessorLineID], [LineID], 1
FROM Lines
WHERE [PredecessorLineID] is null
UNION ALL
SELECT mt.[LineID], mt.[PredecessorLineID], mt.[SuccessorLineID], q.init, q.lvl + 1
FROM q
JOIN Lines mt
ON mt.[LineID] = q.SuccessorLineID
)
select * from q Option ( maxrecursion 4 )
这给出了正确的结果,但问题是递归深度。它实际上是 n - 1。我有几千行,需要将 maxrecursion 设置为一个非常高的值。
这个查询需要在一个视图中,这就是为什么我什至不能设置 maxrecursion 并且需要将它设置为服务器的默认值。
有没有办法用更少的递归来做到这一点?
解决方案
我不建议在 SQL 数据库中以这种方式存储链表。它们处理起来相当麻烦。我的意思是,层次结构很好,但它们通常不超过 100 的深度。“一次性”递归 CTE 可以无限递归。
也就是说,您可能有一个有效的用例。您可以创建 UDF 并设置递归:
create function udf_get_hierarchy ()
returns @q as table (
. . . -- column definitions go here
)
BEGIN
WITH q ([LineID], PredecessorLineID, SuccessorLineID, init, lvl) AS (
SELECT [LineID], [PredecessorLineID], [SuccessorLineID], [LineID], 1
FROM Lines
WHERE [PredecessorLineID] is null
UNION ALL
SELECT mt.[LineID], mt.[PredecessorLineID], mt.[SuccessorLineID], q.init, q.lvl + 1
FROM q JOIN
Lines mt
ON mt.[LineID] = q.SuccessorLineID
)
SELECT *
INTO @q
FROM q
OPTION ( MAXRECURSION 0 );
END;
如果您正在创建一个函数,您可能希望将一个参数传递给它,以获取特定 id 的层次结构。
推荐阅读
- python - 你可以在 python 的 switch-case 中使用变量吗?
- angular - Angular Material自动完成未显示
- c# - 创建数据库时 SQLite Android 磁盘 I/O 错误 10 (266)
- sql - 从表插入到表的最快方法
- inheritance - 疑难解答如何继承Odoo12中的字段(500 Internal Server Error)
- python - Python:生成具有最小和最大位数的唯一随机数列表
- angular - 如何打开 MatDialog 并传递 MatDialogRef
- php - 使用图像修补程序/laravel 填充数据库
- laravel - 如何恢复提交 .gitignore 后消失的 .env 文件
- python-3.x - 主类的第二帧中的小部件不出现