我有一个表格,包含大约70,000行和两列(都是VARCHAR(16)类型):id
和parent_id
。
我想要填充一个“depth”列,显示特定记录距离“根”节点的距离。
例如:
id,parent_id,depth
A,NULL,0
B,A,1
C,A,1
D,B,2
E,D,3
我开始根据这个回答中类似问题的写法编写查询语句:
WITH myCTE(id, depth) AS
(
SELECT id, 0 FROM objects where id = 'A'
UNION ALL
SELECT objects.id, depth + 1 FROM myCTE JOIN objects ON objects.parent_id = myCTE.id
)
SELECT id, depth FROM myCTE
使用我的数据集(约80,000行),上述操作需要近两个小时才能执行完毕!
我随后将查询作为一个循环编写,并获得了更好的性能:
ALTER TABLE objects ADD depth INT NULL
DECLARE @counter int
DECLARE @total int
SET @counter = 0
UPDATE objects SET depth = 0 WHERE id = 'A'
SELECT @total = COUNT(*) FROM objects WHERE depth IS NULL
WHILE (@total > 0)
BEGIN
UPDATE objects SET depth = @counter + 1 WHERE parent_id IN (
SELECT id FROM objects WHERE depth = @counter
)
SELECT @total = COUNT(*) FROM objects WHERE depth IS NULL
SET @counter = @counter + 1
END
以上代码只需要几分钟就可以完成(它还有一个好处,即将结果添加到现有表格中)。
我的问题是,使用CTE解决此问题是否会产生与我相似的结果,或者是否有一些我忽略的东西可能会解释这个问题?也许是索引吗?(目前我没有在表格上创建任何索引)