SQL-缩进多级数字​​列表

时间:2020-08-07 11:14:26

标签: sql-server

我正在尝试基于父/子层次结构表建立查询。 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级)时,它都必须采用先前的行值并从在那里再次计数。 任何帮助,将不胜感激。我试图避免使用循环或游标。 谢谢。

1 个答案:

答案 0 :(得分:0)

此解决方案使用Recursive Common Table Expressionrcte)来获取所需的编号(Number)。我还包括了分层路径(PathWithIds)作为奖励。

您的数据有点不寻常,因为没有行以ChildItemSpecID=1, ParentItemSpecID=null作为根元素。通常,将递归CTE中的根定义为“没有父元素的元素”(ParentItemSpecID=null)。此解决方案采用了更为硬编码的方法,并列出了一些替代方案。

我在结果中省略了TotalQtyPerRootlevelTreeSort列。我不清楚这些列是您的数据还是尝试输出的一部分。如果需要,您可以添加它们,甚至可以将它们计算为递归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
相关问题