我正在尝试使用sql选择值时获取xml节点的索引:
这是代码:
declare @myxml xml ='
<Departments>
<Department>
<Employee>
A
</Employee>
<Employee>
B
</Employee>
</Department>
<Department>
<Employee>
C
</Employee>
<Employee>
D
</Employee>
</Department>
</Departments>'
Select Emp = m.value('.','varchar(30)')
from @myxml.nodes('Departments/Department/Employee') X(m)
上述查询的输出:
Emp
A
B
C
D
预期输出:
Emp Department_Index
A 1
B 1
C 2
D 2
即我想要与部门下每个员工相对应的部门索引。 这里的员工A和B属于第一部门,而员工C和D属于第二部门。
所以我希望这能将复杂的XML子级与没有唯一键的父级连接起来。
答案 0 :(得分:0)
这是一个解决方案,我声称它可以在所有情况下都可以工作-尽管不能保证通过<Department>
绑定到ROW_NUMBER()
节点的数字将反映其在每个场景中的实际位置以及任何情况(请参见下面的备注和链接):
declare @myxml xml ='
<Departments>
<Department>
<Employee>
A
</Employee>
<Employee>
B
</Employee>
</Department>
<Department>
<Employee>
C
</Employee>
<Employee>
D
</Employee>
</Department>
</Departments>';
-查询将使用CTE将数字绑定到第一级并整体传递内部节点 。最终的SELECT将使用传递的<Department>
节点并选择其雇员:
WITH NumberedDepartment AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS DepInx
,d.query(N'.') AS DepartmentNode
FROM @myxml.nodes(N'/Departments/Department') AS A(d)
)
SELECT DepInx
,e.value(N'text()[1]','nvarchar(max)') AS Employee
FROM NumberedDepartment
CROSS APPLY DepartmentNode.nodes(N'Department/Employee') AS B(e);
如果您想了解有关排序顺序的保证 ,请might read this thread。特别值得一读:The chat below John Cappellettis answer。在那边,我提供了一种使用XQuery
的方法,以及另一种使用计数/数字表来选择元素位置的方法。但这是相当复杂且缓慢的。
这种方法将即时创建一个理货单 。如果您有数字表,那就更好了……
TOP
子句会将此计数限制为<Department>
个节点的实际数量。确保使用源表(我使用master..spt_values
),该表至少具有您可能需要的行数。
第一个应用将使用.query()
和sql:column()
来为每个数字获取正确的部门节点。第二个应用程序将读取相关员工。
WITH Tally(Nmbr) AS
(
SELECT TOP (SELECT @myxml.value(N'count(/Departments/Department)','int'))
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM master..spt_values --just a pre-filled table with many rows
)
SELECT Nmbr
,e.value(N'text()[1]','nvarchar(max)') AS Employee
FROM Tally
OUTER APPLY(SELECT @myxml.query(N'/Departments/Department[sql:column("Nmbr")]')) AS A(ds)
OUTER APPLY ds.nodes(N'Department/Employee') AS B(e);