我在 SQL Server 中有一个表示层次结构数据的 XML 结构,我需要根据每个项目在层次结构中的位置来更新每个项目的 ItemNumber。这是我到目前为止所拥有的:
DECLARE @ItemsXml XML =
(
SELECT dbo.GetCurrentLanguageValue(ti.Title, @Language) AS 'EntityTitle',
ti.[Order] AS 'ItemNumber',
ti.ParentId as 'ParentId',
ti.Id as 'Id',
m.RegistrationNumber as 'RegistrationNumber',
CONVERT(NVARCHAR, m.RegistrationDate, 4) AS 'RegistrationDate',
dbo.GetCurrentLanguageValue(s.Title, @Language) AS 'EntityState',
dbo.GetCurrentLanguageValue(mt.Title, @Language) AS 'MaterialTypeTitle',
IIF(m.ProposerMPId is not null,
dbo.GetCurrentLanguageValue(u.FirstName, @Language) + ' ' + dbo.GetCurrentLanguageValue(u.LastName, @Language),
dbo.GetCurrentLanguageValue(m.ResponsibleProposer, @Language)) AS 'EntityProposer',
dbo.AgendaSittingAtachments(ti.Id, @Language) AS 'AgendaSittingAttachment'
FROM TreeItems AS ti
INNER JOIN CategorizationLinks cl ON cl.CategorizationId = ti.CategorizationId
LEFT OUTER JOIN TreeItemValues tiv ON tiv.TreeItemId = ti.Id
LEFT OUTER JOIN Materials m ON m.Id = tiv.MaterialId
LEFT OUTER JOIN MaterialTypes mt on mt.Id = m.[Type]
LEFT OUTER JOIN Statuses s ON s.Id = m.[Status]
LEFT OUTER JOIN Users u ON u.Id = m.ProposerMPId
LEFT OUTER JOIN TreeItems tiParent ON tiParent.Id = ti.ParentId
WHERE cl.SittingId = @ObjectId AND (m.[Type] IS NULL OR m.[Type] not in (24, 51, 57, 58))
AND (ti.EmptyItemTypeId is null or tiParent.TreeItemTypeId <> 3) AND ti.ParentId is not null
ORDER BY ti.[Order]
FOR XML PATH ('Items')
)
<Items>
<EntityTitle>Receive and File a Report from Community Action of the County on the 2023-2024 Community Needs Assessment and Community Action Plan</EntityTitle>
<ItemNumber>1</ItemNumber>
<ParentId>E9BBEF90-0915-41F3-87D0-AAD943C0554F</ParentId>
<Id>BC94E6D1-B8D8-44CE-A7CB-963A048FFCAF</Id>
<EntityState>Business committee consideration</EntityState>
<MaterialTypeTitle>Motion for adoption of the report</MaterialTypeTitle>
<EntityProposer>Epar User1</EntityProposer>
</Items>
<Items>
<EntityTitle>cat2</EntityTitle>
<ItemNumber>1</ItemNumber>
<ParentId>AD4F8BB1-0FE4-4078-BF34-9B509B20A723</ParentId>
<Id>558CD287-BB26-4A76-9388-BC98CC486B30</Id>
</Items>
<Items>
<EntityTitle>cat1</EntityTitle>
<ItemNumber>2</ItemNumber>
<ParentId>E9BBEF90-0915-41F3-87D0-AAD943C0554F</ParentId>
<Id>B0B88E8A-CEAB-4023-9E1C-5F202131D146</Id>
</Items>
<Items>
<EntityTitle>Annual appro #1</EntityTitle>
<ItemNumber>2</ItemNumber>
<ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
<Id>E0B7B388-FB1B-4293-BA80-9FFD161732B2</Id>
<EntityState>Committee consideration I reading</EntityState>
<MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
<EntityProposer>Epar User1</EntityProposer>
</Items>
<Items>
<EntityTitle>Test Kiko Redirect</EntityTitle>
<ItemNumber>2</ItemNumber>
<ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
<Id>AD4F8BB1-0FE4-4078-BF34-9B509B20A723</Id>
<EntityState>Committee consideration I reading</EntityState>
<MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
<EntityProposer>epar_user15 test15</EntityProposer>
</Items>
<Items>
<EntityTitle>Annual Appropriation Bill</EntityTitle>
<ItemNumber>3</ItemNumber>
<ParentId>B0B88E8A-CEAB-4023-9E1C-5F202131D146</ParentId>
<Id>F551FB03-2794-4209-9C29-88C2862CCE57</Id>
<EntityState>Committee consideration I reading</EntityState>
<MaterialTypeTitle>Annual Appropriation Bill </MaterialTypeTitle>
<EntityProposer>Simona Radinska Andovski</EntityProposer>
</Items>
目标是更新 ItemNumber 字段,以便根据项目的层次结构级别对项目进行编号。例如,如果某个项目的父级为 1,则其 ItemNumber 应为 1.1、1.2 等。
我尝试直接在 UPDATE 语句中使用窗口函数,但遇到了限制。
有人可以建议一种替代方法来根据 XML 数据的层次结构有效更新 ItemNumber 字段吗?
谢谢!
您可以使用递归 CTE 来构建项目编号。然后将其他所有内容加入其中。
WITH
或 DECLARE
上使用 SET
,您需要一个 SELECT
。nvarchar(4000)
或 nvarchar(max)
否则您将收到类型绑定错误。n/varchar
。, TYPE
类型,请在 FOR XML
上使用 xml
。tiParent.TreeItemTypeId <> 3
似乎只指直接父级,而不是树的顶部。如果要求不同,那么您需要更改 CTE。dbo.GetCurrentLanguageValue
的作用,但它可能会被分解为内联表值函数,这通常更快。DECLARE @ItemsXml XML;
WITH cte AS (
SELECT
ti.[Order],
ti.ParentId,
ti.Id as Id,
ti.EmptyItemTypeId,
ti.TreeItemTypeId,
NULL AS ParentTreeItemTypeId,
CAST(ti.[Order] AS nvarchar(4000)) AS ItemNumber
FROM TreeItems ti
WHERE ti.ParentId IS NULL
UNION ALL
SELECT
ti.[Order],
ti.ParentId,
ti.Id as Id,
ti.EmptyItemTypeId,
ti.TreeItemTypeId,
cte.TreeItemTypeId,
CONCAT(cte.ItemNumber, N'.', ti.[Order])
FROM TreeItems ti
JOIN cte tiParent ON tiParent.Id = ti.ParentId
)
SELECT @ItemsXml =
(
SELECT
dbo.GetCurrentLanguageValue(ti.Title, @Language) AS EntityTitle,
ti.ItemNumber,
ti.ParentId,
ti.Id,
m.RegistrationNumber,
CONVERT(NVARCHAR(30), m.RegistrationDate, 4) AS RegistrationDate,
dbo.GetCurrentLanguageValue(s.Title, @Language) AS EntityState,
dbo.GetCurrentLanguageValue(mt.Title, @Language) AS MaterialTypeTitle,
IIF(m.ProposerMPId is not null,
dbo.GetCurrentLanguageValue(u.FirstName, @Language) + ' ' + dbo.GetCurrentLanguageValue(u.LastName, @Language),
dbo.GetCurrentLanguageValue(m.ResponsibleProposer, @Language)) AS EntityProposer,
dbo.AgendaSittingAtachments(ti.Id, @Language) AS AgendaSittingAttachment
FROM cte AS ti
INNER JOIN CategorizationLinks cl ON cl.CategorizationId = ti.CategorizationId
LEFT OUTER JOIN TreeItemValues tiv ON tiv.TreeItemId = ti.Id
LEFT OUTER JOIN Materials m ON m.Id = tiv.MaterialId
LEFT OUTER JOIN MaterialTypes mt on mt.Id = m.[Type]
LEFT OUTER JOIN Statuses s ON s.Id = m.Status
LEFT OUTER JOIN Users u ON u.Id = m.ProposerMPId
LEFT OUTER JOIN TreeItems tiParent ON tiParent.Id = ti.ParentId
WHERE cl.SittingId = @ObjectId
AND (m.[Type] IS NULL OR m.[Type] not in (24, 51, 57, 58))
AND (ti.EmptyItemTypeId is null or ti.ParentTreeItemTypeId <> 3)
AND ti.ParentId is not null
ORDER BY ti.[Order]
FOR XML PATH ('Items'), TYPE
);