2011-07-07 57 views
6

我有一个包含主对象的子对象的表。任何孩子可以出现多次,并没有包含该号码出现次数列,所以在表中的数据是一样的东西:多次选择同一行

ChildID | ParentID | Occurences 
------------------------------- 
     1 |  1 |  2 
     2 |  1 |  2 
     3 |  2 |  1 
     4 |  2 |  3 

我需要让所有的孩子的列表,每个孩子出现在结果的次数corect数,像

IDENT | ChildID | ParentID 
-------------------------- 
    1 |  1 |  1 
    2 |  1 |  1 
    3 |  2 |  1 
    4 |  2 |  1 
    5 |  3 |  2 
    6 |  4 |  2 
    7 |  4 |  2 
    8 |  4 |  2 

我可以用循环表并插入尽可能多的行作为neccessary光标做到这一点,但我不认为这是最好的解决办法可能。

感谢您的帮助


创建脚本包括:

DECLARE @Children TABLE (ChildID int, ParentID int, Occurences int) 

INSERT @Children 
SELECT 1, 1, 2 UNION ALL 
SELECT 2, 1, 2 UNION ALL 
SELECT 3, 2, 1 UNION ALL 
SELECT 4, 2, 3 
+1

如果我问你为什么需要这样做,你介意吗?也许有一种比多次选择同一行更好的方法。 – EdoDodo

+0

我需要为每个孩子生成一行,因为有一些额外的数据可能不同。 – SWeko

回答

7
;with C as 
(
    select ChildID, 
     ParentID, 
     Occurences - 1 as Occurences 
    from @Children 
    union all 
    select ChildID, 
     ParentID, 
     Occurences - 1 as Occurences 
    from C 
    where Occurences > 0 
) 
select row_number() over(order by ChildID) as IDENT, 
     ChildID, 
     ParentID 
from C 
order by IDENT 
+0

Thx,诀窍 – SWeko

+0

真棒诀窍:) – SMK

+0

另外一件事情,在我的情况下,发生次数很少(10上),但如果数量在数百,这将超过递归限制。 – SWeko

4
;WITH CTEs 
AS 
(
    SELECT 1 [Id] 
    UNION ALL 
    SELECT [Id] + 1 FROM CTEs WHERE [Id] < 100 
) 
SELECT ROW_NUMBER() OVER(ORDER BY c1.ChildID, c1.ParentID) [rn] 
    , c1.ChildID, c1.ParentID 
FROM CTEs ct 
JOIN @Children c1 ON c1.Occurences >= ct.[Id] 

另一种方式来生成序列使用预定义的表格,例如master.dbo.spt_values

SELECT ROW_NUMBER() OVER(ORDER BY c1.ChildID, c1.ParentID) [rn] 
    , c1.ChildID, c1.ParentID 
FROM master.dbo.spt_values ct 
JOIN @Children c1 ON c1.Occurences > ct.number 
    AND ct.type = 'P' 
+0

酷,这基本上加入了源表与数字表,并有一个很好的连接条件。 – SWeko

+0

在我的情况下,发生次数很少(10次),但如果次数在几百次,则会超过递归限制。如果数字表是预生成的,那么这可能会被回避。 – SWeko

+0

或用“选项(MAXRECURSION 0)”进行回避 –