我再次遇到一个小问题(我希望很小)。
我有一个父母孩子hirarchy,其中一方父母可以有多个孩子,一个孩子可以再生多个孩子等等。
每个父母和子女都有一定数额(价值),父母可以补偿儿童的任何遗失金额。
这是我的表:
CREATE TABLE #Test
(
ID INTEGER NOT NULL
,ParentID INTEGER
,NAME VARCHAR(20)
,value INTEGER
)
TESTDATA:
INSERT INTO #Test
( ID, ParentID, NAME, value )
VALUES ( 1, NULL, 'MainStore', 1 )
, ( 2, 1, 'Substore1', 3 )
, ( 3, 1, 'Substore2', 10 )
, ( 4, 2, 'Sub1Substore1', -1 )
, ( 5, 2, 'Sub1Substore2', 1 )
, ( 6, 3, 'Sub2Substore1', 10 )
要显示父亲关系,我已尝试使用CTE:
;WITH CTE
AS ( SELECT ID
,ParentID
,Name
,Value
,0 AS LEVEL
,CAST('' AS INTEGER) AS ID_Parent
FROM #Test
WHERE ParentID IS NULL
UNION ALL
SELECT child.ID
,child.ParentID
,child.Name
,child.Value
,parent.Level + 1
,parent.ID
FROM CTE parent
JOIN #Test child ON child.ParentID = parent.ID
)
如您所见,Substore1有2个子级(Sub1Substore1和Sub1Substore2),Substore1的值为3,Sub1Substore1为-1,Sub1Substore2为1。
Sub1Substore1是Substore1的子节点,父节点可以补偿子节点的缺失值。
我想要的输出应该如下所示:
ID ParentID Name Value LEVEL ID_Parent FreeValues
----------- ----------- -------------------- ----------- ----------- ----------- -----------
1 NULL MainStore 1 0 0 1
2 1 Substore1 3 1 1 2
3 1 Substore2 10 1 1 8
4 2 Sub1Substore1 -1 2 2 0
5 2 Sub1Substore2 1 2 2 1
6 3 Sub2Substore1 -2 2 3 0
可悲的是,SQL Fiddle网站暂时不适合我,但我稍后将在SQL Fiddle上提供此示例。
答案 0 :(得分:1)
编辑:由于误解了任务,重写了整个答案。
这可能可以通过常见的表表达式优雅地解决,但由于CTE缺乏对多个递归引用的支持,因此这个任务似乎变得过于复杂,我无法处理。
然而,这是一个不太优雅的解决方案,应该为你做的伎俩。请注意,我假设父母的ID总是小于它的直接子女的身份。如果您应该能够更改已插入的行"即时",这可能会成为一个问题。无论如何,你走了:
--Declare temp table.
DECLARE @Temp TABLE
(
ID INTEGER NOT NULL
,ParentID INTEGER
,NAME VARCHAR(20)
,value INTEGER
,FreeValues INTEGER
,NeedFromParent INTEGER
,ChildrenNeed INTEGER
);
--Other variables
DECLARE @ID INTEGER
DECLARE @ParentID INTEGER
DECLARE @Name VARCHAR(20)
DECLARE @value INTEGER
DECLARE @FreeValues INTEGER
DECLARE @NeedFromParent INTEGER
DECLARE @ChildrenNeed INTEGER
--Loop with cursor to calculate FreeValues
DECLARE cur CURSOR FOR SELECT id, parentId, Name, Value FROM #test
ORDER BY ID DESC -- NOTE! Assumed that Parent's ID < Child's ID.
OPEN cur
FETCH NEXT FROM cur INTO @ID, @ParentID, @Name, @value
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @ChildrenNeed = CASE
WHEN SUM(temp.NeedFromParent) IS NULL THEN 0
ELSE SUM(temp.NeedFromParent) END
FROM @temp temp WHERE temp.ParentID=@ID AND temp.NeedFromParent > 0
IF @ChildrenNeed IS NULL SET @ChildrenNeed = 0
IF @Value - @ChildrenNeed < 0
SET @NeedFromParent = @Value - @ChildrenNeed
ELSE
SET @NeedFromParent = 0
SET @NeedFromParent = -@NeedFromParent
IF @NeedFromParent = 0
SET @FreeValues = @value - @ChildrenNeed
ELSE
SET @FreeValues = 0
INSERT INTO @Temp
VALUES(@ID, @ParentID, @Name, @value, @FreeValues, @NeedFromParent, @ChildrenNeed)
FETCH NEXT FROM cur INTO @ID, @ParentID, @Name, @value
END
CLOSE cur;
DEALLOCATE cur;
-- Join with recursively calculated Level.
;WITH CTE
AS ( SELECT ID ,ParentID,0 AS [Level]
FROM #Test WHERE ParentID IS NULL
UNION ALL
SELECT child.ID,child.ParentID,parent.Level + 1
FROM CTE parent INNER JOIN #Test child ON child.ParentID = parent.ID
)
SELECT t1.ID, t1.ParentID, t1.Name, t1.Value, cte.[Level], t1.FreeValues
FROM CTE cte LEFT JOIN @temp t1 ON t1.ID = cte.ID
ORDER BY ID