在SQL中为基于NextId的层次结构顺序创建排序列

时间:2016-04-26 19:53:06

标签: sql sql-server hierarchy

我在SQL中有一个层次结构表,包含NodeId,ParentId,ChildId,NextId,NodeLevel和有效期(DateFrom,DateTo),因为层次结构中节点的位置可以根据日期而改变。我可以使用NodeId和ParentId递归循环遍历记录,没有任何问题。我遗漏的部分是如何订购节点。节点的顺序基于ChildId,NextId和有效期。我需要一种基于有效期动态添加排序列的方法。这应该给我一个名为SortOrder的列,它只是按顺序对节点进行编号,如果显示的层次结构向下扩展到最低级别。重新创建我正在使用的表的代码是:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[NextIDTest](
    [NodeName] [nvarchar](60) NOT NULL,
    [NodeId] [int] NOT NULL,
    [ParentId] [int] NOT NULL,
    [ChildId] [int] NOT NULL,
    [NextId] [int] NOT NULL,
    [NodeLevel] [int] NOT NULL,
    [DateFrom] [date] NOT NULL,
    [DateTo] [date] NOT NULL
) ON [PRIMARY]

GO

INSERT [dbo].[NextIDTest] ([NodeName], [NodeId], [ParentId], [ChildId], [NextId], [NodeLevel], [DateFrom], [DateTo]) 
VALUES 
(N'TOTAL CAPITAL EXPENDITURE', 1, 0, 2, 0, 1, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'UTILITY CAPITAL EXPENDITURES', 2, 1, 3, 28, 2, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 1', 3, 2, 4, 24, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'NEW MAINS', 4, 3, 7, 9, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000713', 5, 4, 0, 8, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000712', 6, 4, 0, 5, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000711', 7, 4, 0, 6, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00007199', 8, 4, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'NEW SERVICES', 9, 3, 13, 14, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00007299', 10, 9, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000723', 11, 9, 0, 10, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000722', 12, 9, 0, 11, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000721', 13, 9, 0, 12, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000777', 14, 3, 0, 17, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000740', 15, 3, 0, 16, 4, CAST(N'1000-01-01' AS Date), CAST(N'2014-11-30' AS Date))
,(N'00000586', 16, 3, 0, 18, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000015', 17, 3, 0, 15, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'METERS', 18, 3, 20, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000023', 19, 18, 0, 21, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000021', 20, 18, 0, 19, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'IND AND COMM SOLUTIONS', 21, 18, 23, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000024', 22, 21, 0, 0, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000022', 23, 21, 0, 22, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 2', 24, 2, 25, 29, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'BARE STEEL', 25, 24, 27, 40, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000319', 26, 25, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000119', 27, 25, 0, 26, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'NON-UTILITY CAPITAL EXPENDITURES', 28, 1, 35, 0, 2, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 3', 29, 2, 52, 30, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 4', 30, 2, 55, 31, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 5', 31, 2, 57, 32, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 6', 32, 2, 125, 129, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'NON-UTILITY', 33, 28, 122, 0, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'BUSINESS DEVELOPMENT', 34, 28, 120, 33, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'GAS STORAGE', 35, 28, 95, 34, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000320', 37, 24, 0, 39, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000120', 38, 24, 0, 37, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000112', 39, 24, 0, 127, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'LEAKAGE', 40, 24, 59, 128, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'GENERAL', 41, 29, 79, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'GAS SUPPLY', 42, 29, 71, 41, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'REGULATORS', 43, 29, 66, 42, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000336', 44, 29, 0, 46, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000318', 45, 29, 0, 43, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000317', 46, 29, 0, 45, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000140', 47, 29, 0, 50, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000136', 48, 29, 0, 44, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000115', 49, 29, 0, 47, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000014', 50, 29, 0, 48, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'RELOCATES/ABANDONMENTS', 51, 29, 64, 126, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'PUBLIC WORKS', 52, 29, 62, 51, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000585', 53, 30, 0, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'LAND AND STRUCTURES', 54, 30, 86, 53, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'INFORMATION TECHNOLOGY', 55, 30, 83, 54, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'TOTAL NON-UTIL INTERSTATE STOR', 56, 31, 93, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'TOTAL UTILITY STORAGE PROJECTS', 57, 31, 87, 56, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000313', 58, 40, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000113', 59, 40, 0, 58, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000314', 60, 52, 0, 61, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000117', 61, 52, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000114', 62, 52, 0, 60, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000316', 63, 51, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000116', 64, 51, 0, 63, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000019', 65, 43, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000013', 66, 43, 0, 65, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000529', 67, 42, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000524', 68, 42, 0, 67, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000018', 69, 42, 0, 68, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000012', 70, 42, 0, 69, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000011', 71, 42, 0, 70, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000571', 72, 41, 0, 73, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000509', 73, 41, 0, 74, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000044', 74, 41, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000043', 75, 41, 0, 76, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000040', 76, 41, 0, 80, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000035', 77, 41, 0, 78, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000033', 78, 41, 0, 75, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000032', 79, 41, 0, 77, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000031', 80, 41, 0, 72, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000039', 81, 55, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000038', 82, 55, 0, 81, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000017', 83, 55, 0, 82, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000511', 84, 54, 0, 85, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000036', 85, 54, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000034', 86, 54, 0, 84, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000569', 87, 57, 0, 88, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000562', 88, 57, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000581', 89, 56, 0, 90, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000563', 90, 56, 0, 124, 5, CAST(N'1000-01-01' AS Date), CAST(N'2014-11-30' AS Date))
,(N'00000514', 91, 56, 0, 92, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000513', 92, 56, 0, 89, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000512', 93, 56, 0, 91, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'GAS STORAGE LLC', 94, 35, 116, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'OTHER STORAGE', 95, 35, 96, 94, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'OTHER (COMPANY 1234)', 96, 95, 111, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000480', 97, 96, 0, 112, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000470', 98, 96, 0, 97, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000460', 99, 96, 0, 98, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000450', 100, 96, 0, 99, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000440', 101, 96, 0, 100, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000430', 102, 96, 0, 101, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000420', 104, 96, 0, 102, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000410', 111, 96, 0, 104, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000401', 112, 96, 0, 0, 6, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000491', 113, 94, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000489', 114, 94, 0, 117, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000486', 115, 94, 0, 113, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000481', 116, 94, 0, 114, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000413', 117, 94, 0, 115, 5, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000508', 118, 34, 0, 119, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000507', 119, 34, 0, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000506', 120, 34, 0, 121, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000505', 121, 34, 0, 118, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000587', 122, 33, 0, 123, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000510', 123, 33, 0, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000564', 124, 56, 0, 0, 5, CAST(N'1000-01-01' AS Date), CAST(N'2014-11-30' AS Date))
,(N'00000760', 125, 32, 0, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000752', 126, 29, 0, 49, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000751', 127, 24, 0, 0, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000750', 128, 24, 0, 38, 4, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'CATEGORY 7', 129, 2, 132, 0, 3, CAST(N'1000-01-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000740', 130, 129, 0, 0, 4, CAST(N'2014-12-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000564', 131, 129, 0, 130, 4, CAST(N'2014-12-01' AS Date), CAST(N'9999-12-31' AS Date))
,(N'00000563', 132, 129, 0, 131, 4, CAST(N'2014-12-01' AS Date), CAST(N'9999-12-31' AS Date))
GO

编辑:

预期输出将如下所示:

NodeName                                                     NodeId      ParentId    ChildId     NextId      NodeLevel   SortOrder
------------------------------------------------------------ ----------- ----------- ----------- ----------- ----------- -----------
TOTAL CAPITAL EXPENDITURE                                    1           0           2           0           1           1
UTILITY CAPITAL EXPENDITURES                                 2           1           3           28          2           2
CATEGORY 1                                                   3           2           4           24          3           3
NEW MAINS                                                    4           3           7           9           4           4
00000713                                                     5           4           0           8           5           7
00000712                                                     6           4           0           5           5           6
00000711                                                     7           4           0           6           5           5
00007199                                                     8           4           0           0           5           8

1 个答案:

答案 0 :(得分:1)

我不知道我是否真的得到了这个,但这可能就是你要找的东西:

顺便说一句:您不需要表中的所有这些列(ChildId,NextId和NodeLevel将来自查询)。实际上将它们保存为存储值是非常错误的......

顺便说一句:下次请尝试将您的示例缩减为少量行,并将预期的输出拟合添加到给定数据中。这使您更容易理解您真正需要的东西......

--A recursive CTE traverses down the hierarchy
WITH RecCTE AS
(
    SELECT NodeName,NodeId,ParentId,1 AS NodeLevel,DateFrom,DateTo 
    FROM NextIDTest
    WHERE ParentId=0
    UNION ALL
    SELECT y.NodeName,y.NodeId,y.ParentId,x.NodeLevel+1,y.DateFrom,y.DateTo
    FROM RecCTE AS x
    INNER JOIN NextIDTest AS y ON x.NodeId=y.ParentId
)
--the second CTE will take the ResultSet as it comes out of recCTE and number it
,Numbered AS --
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RunningNumber,*
    FROM RecCTE
)
--the third CTE will get another numbering, don't know if this really is what you need
,InternalSort AS
(
    SELECT ROW_NUMBER() OVER(PARTITION BY NodeLevel ORDER BY DateFrom DESC,RunningNumber) AS InternalSort,*
    FROM Numbered
)
--And finally this is again numbered "as is"
SELECT  ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS YourSortColumn,*
FROM InternalSort