我在MS SQL中有以下递归表值函数,以便从数据库中检索对象的层次结构:
WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr, Iteration) AS
(
SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, 1
FROM Field
WHERE Field.ParentNum = @ParentNum
UNION ALL
SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, tmpField.Iteration + 1
FROM Field INNER JOIN
tmpField on Field.ParentNum = tmpField.ChildNum
)
SELECT DISTINCT ParentNum AS ParentNum, ChildNum AS ChildNum, FieldNum, FieldDescr
FROM tmpField
我想通过以下方式修改它:
在 last 迭代中,当没有“子”时,我希望ChildNum
字段的值为FieldNum
。在之前的所有迭代中,ChildNum
应该具有ChildNum
字段的值,就像现在一样。
有人建议使用上述查询作为起点来实现此目的吗?
请注意:尽管名称如此,但字段ChildNum
不引用任何子行,但应将其解释为该行的标识符。
答案 0 :(得分:2)
当没有更多子项时,意味着ChildNum为NULL,所以:
...
UNION ALL
SELECT Field.ParentNum,
COALESCE(Field.ChildNum, Field.FieldNum) ChildNum,
Field.FieldNum,
...
编辑:(跟随大安评论)
好的,在这种情况下,我们可以查看ChildNum'孩子的计数:
...
UNION ALL
SELECT F1.ParentNum,
CASE WHEN (SELECT COUNT(1)
FROM FIELD F2
WHERE F2.ParentNum = F1.ChildNum) = 0
THEN F1.FieldNum
ELSE F1.ChildNum
END ChildNum,
F1.FieldNum, F1.FieldDescr, tmpField.Iteration + 1
FROM Field F1 INNER JOIN
tmpField on F1.ParentNum = tmpField.ChildNum
...
EDIT2:
让我们把支票搬到外面:
WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr, Iteration) AS
(
SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, 1
FROM Field
WHERE Field.ParentNum = @ParentNum
UNION ALL
SELECT Field.ParentNum, Field.ChildNum, Field.FieldNum, Field.FieldDescr, tmpField.Iteration + 1
FROM Field INNER JOIN
tmpField on Field.ParentNum = tmpField.ChildNum
)
SELECT DISTINCT ParentNum AS ParentNum,
CASE WHEN EXISTS (SELECT NULL
FROM Field f
WHERE tmpField.ChildNum = f.ParentNum)
THEN tmpField.ChildNum
ELSE tmpField.FieldNum
END ChildNum,
FieldNum,
FieldDescr
FROM tmpField
答案 1 :(得分:1)
这应该返回您需要的数据。 我删除了迭代,因为你以后不再使用它
加入版本
;WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr) AS
(
SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr
FROM Field f
WHERE f.ParentNum = @ParentNum
UNION ALL
SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr
FROM Field f
INNER JOIN tmpField on f.ParentNum = tmpField.ChildNum
)
SELECT t.ParentNum AS ParentNum,
Case When p.ParentNum is Null
Then t.FieldNum
Else t.ChildNum
End AS ChildNum,
t.FieldNum,
t.FieldDescr
FROM tmpField t
Left Join (Select distinct ParentNum From Field) p on t.ChildNum=p.ParentNum
或
SUBQUERY VERSION(修改为使用EXISTS代替COUNT)
;WITH tmpField (ParentNum, ChildNum, FieldNum, FieldDescr) AS
(
SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr
FROM Field f
WHERE f.ParentNum = @ParentNum
UNION ALL
SELECT f.ParentNum, f.ChildNum, f.FieldNum, f.FieldDescr
FROM Field f
INNER JOIN tmpField on f.ParentNum = tmpField.ChildNum
)
SELECT t.ParentNum AS ParentNum,
Case When Exists(Select * from Field p Where t.ChildNum=p.ParentNum)
Then t.ChildNum
Else t.FieldNum
End AS ChildNum,
t.FieldNum,
t.FieldDescr
FROM tmpField t