我在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

我想修改它以下述方式:

最后的迭代,当没有更多的“孩子”,我想ChildNum领域有FieldNum的价值。在所有以前的迭代,ChildNum应该有ChildNum字段的值,因为它是现在。

任何人都可以提供一个方法来实现这一点,使用上述查询作为起点?

请注意:尽管它的名字,现场ChildNum没有引用行的任何子女,但应理解为该行的标识符。

有帮助吗?

解决方案

当没有更多的孩子就意味着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

其他提示

这应该返回你需要的数据。 我删除重复,你不要用到它。

JOIN VERSION

;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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top