显示此问题的是您的交叉应用与您的节点语句列出了两次。使用“查询”扩展名使用“节点”语法执行您正在执行的操作,而不是使用“值”扩展名来直接从扩展名中显示 xml 中的内容,而不是依赖交叉应用的节点。问题是您没有向观众展示您从哪里获得该 ID?您是否确定在运行时从 xml 本身或加入另一个表或不存在 xml 的另一部分?本质上,节点发生的事情是交叉应用并说:“我在该节点层次结构中有两个值,它们在这里。” 然后你再次交叉应用一个不同的节点,它两次返回相同的东西。在使用 cross apply 两次时,您必须小心它正在做的事情。我可以显示差异,但我不知道您与 1 相关联(您是否只是以某种方式为访问者之后的 int 寻找它?)我不知道如何准确地表示您想要的东西。
编辑:好的,这就是我当时的想法。现在我的代码可能比一些代码长,我承认可能有更简单的方法可以做到这一点,但是我会做三件事:
- 保持你的交叉应用与节点,因为节点是有用的,因为它会重复你需要依靠的行。但是,我会为您用于节点的名称添加一个人工标志。然后我将使用节点将两个选择语句联合在一起。
- 然后,我将使用嵌套选择作为 from 语句,然后根据我刚刚设置的标志使用窗口函数确定行号。
- 然后我会再次嵌套它,然后使用与行号的 Id 完全相同的行号,然后我会根据我任意设置的标志基于 max(case when) 进行一些语法旋转。
我通常更喜欢 cte,但由于您的 XML 命名空间有一个“with”开头,而且第一个 cte 也是如此,我忘记了语法是如何解决这个问题的。嵌套选择恕我直言,当有多个时,我会选择 CTE,但在这种情况下,我在另一个嵌套选择中做了一个嵌套选择。我希望这有帮助:
declare @xml xml = '<upx:Root xmlns:upx="http://www.w3.org/2001/XMLSchema">
<upx:Visitors>
<upx:Visitor>Visitor1</upx:Visitor>
<upx:Visitor>Visitor2</upx:Visitor>
</upx:Visitors>
<upx:Senders>
<upx:Sender>Sender1</upx:Sender>
</upx:Senders>
</upx:Root>'
;
declare @Xmltable table ( xmlDocument xml);
insert into @XmlTable values (@xml);
WITH XMLNAMESPACES (default 'http://www.w3.org/2001/XMLSchema')
select
pos as Id
, max(case when Listing = 'Visitors' then Value end) as Visitors
, max(case when Listing = 'Senders' then Value end) as Senders
from
(
select
*
, row_number() over(partition by Listing order by Value) as pos
from
(
SELECT
'Visitors' as Listing
, a.value('.', 'NVARCHAR(50)') AS Value
FROM @XmlTable AS X
CROSS APPLY xmlDocument.nodes('Root/Visitors/Visitor') AS aa(a)
union
SELECT
'Senders'
, b.value('distinct-values(.)', 'NVARCHAR(50)') AS Sender
FROM @XmlTable AS X
CROSS APPLY xmlDocument.nodes('Root/Senders/Sender') AS bb(b)
) as u
) as listing
group by pos