我正在尝试基于父/子层次结构表建立查询。 IE浏览器,我有一个parentID,并且有一个childID。但是,那个ChildID也可能是父代,并且沿着我们走的那棵树。 但是,目标是获得一列输出,该输出将结构表示为数字。例如:
1
1.1
1.1.1
1.1.2
1.1.3
1.2
我在这里SQL Fiddle
有示例表结构CREATE TABLE [dbo].[_test](
[ParentItemSpecID] [int] NULL,
[ChildItemSpecID] [int] NULL,
[TotalQtyPerRoot] [float] NULL,
[level] [float] NULL,
[TreeSort] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (1, 2, 1, 1, 0)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (2, 3, 1, 2, 1)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 4, 1, 3, 2)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (4, 5, 1, 4, 3)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (5, 6, 1, 5, 4)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 7, 1, 6, 5)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 8, 1, 6, 6)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 9, 2, 6, 7)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 10, 1, 6, 8)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 11, 1, 6, 9)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (6, 12, 1, 6, 10)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (5, 13, 1, 5, 11)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (4, 14, 1, 4, 12)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 15, 1, 3, 13)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 16, 2, 3, 14)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 17, 1, 3, 15)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 18, 7, 3, 16)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 19, 2, 3, 17)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 20, 2, 3, 18)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 21, 2, 3, 19)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 22, 1, 3, 20)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 23, 1, 3, 21)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 24, 24, 3, 22)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 25, 24, 3, 23)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 26, 24, 3, 24)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 27, 2, 3, 25)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 28, 4, 4, 26)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 29, 2, 4, 27)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 30, 4, 4, 28)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 31, 2, 4, 29)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 32, 2, 4, 30)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 33, 2, 4, 31)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 34, 2, 4, 32)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 35, 2, 4, 33)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 36, 4, 4, 34)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 37, 2, 4, 35)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (27, 38, 0.04, 4, 36)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 39, 4, 3, 37)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 40, 1, 3, 38)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 41, 1, 3, 39)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 42, 1, 3, 40)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 43, 2, 3, 41)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (3, 44, 1, 3, 42)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (44, 45, 1, 4, 43)
GO
INSERT [dbo].[_test] ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES (45, 46, 1, 5, 44)
GO
如果您引用父母ID 3,孩子ID27。此时,编号应类似于1.1.14,然后开始转到1.1.14.1、1.1.14.2、1.1.14.3
我尝试了许多等级,row_number(),Dense_rank ...我无法理解,每次升级到新级别(+1级)时,它都必须采用先前的行值并从在那里再次计数。 任何帮助,将不胜感激。我试图避免使用循环或游标。 谢谢。
答案 0 :(得分:0)
此解决方案使用Recursive Common Table Expression(rcte
)来获取所需的编号(Number
)。我还包括了分层路径(PathWithIds
)作为奖励。
您的数据有点不寻常,因为没有行以ChildItemSpecID=1, ParentItemSpecID=null
作为根元素。通常,将递归CTE中的根定义为“没有父元素的元素”(ParentItemSpecID=null
)。此解决方案采用了更为硬编码的方法,并列出了一些替代方案。
我在结果中省略了TotalQtyPerRoot
,level
和TreeSort
列。我不清楚这些列是您的数据还是尝试输出的一部分。如果需要,您可以添加它们,甚至可以将它们计算为递归CTE的一部分。
样本数据
declare @_test table
(
[ParentItemSpecID] [int] NULL,
[ChildItemSpecID] [int] NULL,
[TotalQtyPerRoot] [float] NULL,
[level] [float] NULL,
[TreeSort] [int] NULL
);
INSERT @_test ([ParentItemSpecID], [ChildItemSpecID], [TotalQtyPerRoot], [level], [TreeSort]) VALUES
(1, 2, 1, 1, 0),
(2, 3, 1, 2, 1),
(3, 4, 1, 3, 2),
(4, 5, 1, 4, 3),
(5, 6, 1, 5, 4),
(6, 7, 1, 6, 5),
(6, 8, 1, 6, 6),
(6, 9, 2, 6, 7),
(6, 10, 1, 6, 8),
(6, 11, 1, 6, 9),
(6, 12, 1, 6, 10),
(5, 13, 1, 5, 11),
(4, 14, 1, 4, 12),
(3, 15, 1, 3, 13),
(3, 16, 2, 3, 14),
(3, 17, 1, 3, 15),
(3, 18, 7, 3, 16),
(3, 19, 2, 3, 17),
(3, 20, 2, 3, 18),
(3, 21, 2, 3, 19),
(3, 22, 1, 3, 20),
(3, 23, 1, 3, 21),
(3, 24, 24, 3, 22),
(3, 25, 24, 3, 23),
(3, 26, 24, 3, 24),
(3, 27, 2, 3, 25),
(27, 28, 4, 4, 26),
(27, 29, 2, 4, 27),
(27, 30, 4, 4, 28),
(27, 31, 2, 4, 29),
(27, 32, 2, 4, 30),
(27, 33, 2, 4, 31),
(27, 34, 2, 4, 32),
(27, 35, 2, 4, 33),
(27, 36, 4, 4, 34),
(27, 37, 2, 4, 35),
(27, 38, 0.04, 4, 36),
(3, 39, 4, 3, 37),
(3, 40, 1, 3, 38),
(3, 41, 1, 3, 39),
(3, 42, 1, 3, 40),
(3, 43, 2, 3, 41),
(3, 44, 1, 3, 42),
(44, 45, 1, 4, 43),
(45, 46, 1, 5, 44);
解决方案
with rcte as
(
select t1.ChildItemSpecID,
t1.ParentItemSpecID,
convert(nvarchar, convert(nvarchar, t1.ParentItemSpecID) + '/' + convert(nvarchar, t1.ChildItemSpecID)) as 'PathWithIds',
convert(nvarchar, 1) as 'Number'
from @_test t1
where t1.ParentItemSpecID = 1 -- select root element (option 1)
-- t1.ChildItemSpecID = 2 -- select root element (option 2)
-- t1.level = 1 -- select root element (option 3)
union all
select t2.ChildItemSpecID,
t2.ParentItemSpecID,
convert(nvarchar, t1.PathWithIds + '/' + convert(nvarchar, t2.ChildItemSpecID)), -- extend number starting from parent number
convert(nvarchar, t1.Number + '.' + convert(nvarchar, row_number() over(order by t2.ChildItemSpecID)))
from @_test t2
join rcte t1
on t1.ChildItemSpecID = t2.ParentItemSpecID
)
select rcte.ChildItemSpecID, rcte.ParentItemSpecID, rcte.PathWithIds, rcte.Number
from rcte
order by rcte.Number;
结果
ChildItemSpecID ParentItemSpecID PathWithIds Number
--------------- ---------------- ---------------- -------------
2 1 1/2 1
3 2 1/2/3 1.1
4 3 1/2/3/4 1.1.1
5 4 1/2/3/4/5 1.1.1.1
6 5 1/2/3/4/5/6 1.1.1.1.1
7 6 1/2/3/4/5/6/7 1.1.1.1.1.1
8 6 1/2/3/4/5/6/8 1.1.1.1.1.2
9 6 1/2/3/4/5/6/9 1.1.1.1.1.3
10 6 1/2/3/4/5/6/10 1.1.1.1.1.4
11 6 1/2/3/4/5/6/11 1.1.1.1.1.5
12 6 1/2/3/4/5/6/12 1.1.1.1.1.6
13 5 1/2/3/4/5/13 1.1.1.1.2
14 4 1/2/3/4/14 1.1.1.2
23 3 1/2/3/23 1.1.10
24 3 1/2/3/24 1.1.11
25 3 1/2/3/25 1.1.12
26 3 1/2/3/26 1.1.13
27 3 1/2/3/27 1.1.14
28 27 1/2/3/27/28 1.1.14.1
37 27 1/2/3/27/37 1.1.14.10
38 27 1/2/3/27/38 1.1.14.11
29 27 1/2/3/27/29 1.1.14.2
30 27 1/2/3/27/30 1.1.14.3
31 27 1/2/3/27/31 1.1.14.4
32 27 1/2/3/27/32 1.1.14.5
33 27 1/2/3/27/33 1.1.14.6
34 27 1/2/3/27/34 1.1.14.7
35 27 1/2/3/27/35 1.1.14.8
36 27 1/2/3/27/36 1.1.14.9
39 3 1/2/3/39 1.1.15
40 3 1/2/3/40 1.1.16
41 3 1/2/3/41 1.1.17
42 3 1/2/3/42 1.1.18
43 3 1/2/3/43 1.1.19
15 3 1/2/3/15 1.1.2
44 3 1/2/3/44 1.1.20
45 44 1/2/3/44/45 1.1.20.1
46 45 1/2/3/44/45/46 1.1.20.1.1
16 3 1/2/3/16 1.1.3
17 3 1/2/3/17 1.1.4
18 3 1/2/3/18 1.1.5
19 3 1/2/3/19 1.1.6
20 3 1/2/3/20 1.1.7
21 3 1/2/3/21 1.1.8
22 3 1/2/3/22 1.1.9