1

我有以下查询,我试图从第二种.value方法返回不同的值。

这是我尝试过的。我尝试添加'distinct-values(.)'只返回不同的值,但它仍然返回与正常相同的结果'.' 如何从一列中选择不同的值?

;WITH XMLNAMESPACES (default 'http://www.w3.org/2001/XMLSchema')

SELECT  

              a.value('.', 'NVARCHAR(50)') AS Visitor          
            , b.value('distinct-values(.)', 'NVARCHAR(50)') AS Sender
FROM         XmlTable AS X 

            CROSS APPLY xmlDocument.nodes('Root/Visitors/Visitor') AS aa(a) 
            CROSS APPLY xmlDocument.nodes('Root/Senders/Sender') AS bb(b)

这是正常结果

在此处输入图像描述

这就是我想要得到的

在此处输入图像描述

像这样

<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>
4

1 回答 1

2

显示此问题的是您的交叉应用与您的节点语句列出了两次。使用“查询”扩展名使用“节点”语法执行您正在执行的操作,而不是使用“值”扩展名来直接从扩展名中显示 xml 中的内容,而不是依赖交叉应用的节点。问题是您没有向观众展示您从哪里获得该 ID?您是否确定在运行时从 xml 本身或加入另一个表或不存在 xml 的另一部分?本质上,节点发生的事情是交叉应用并说:“我在该节点层次结构中有两个值,它们在这里。” 然后你再次交叉应用一个不同的节点,它两次返回相同的东西。在使用 cross apply 两次时,您必须小心它正在做的事情。我可以显示差异,但我不知道您与 1 相关联(您是否只是以某种方式为访问者之后的 int 寻找它?)我不知道如何准确地表示您想要的东西。

编辑:好的,这就是我当时的想法。现在我的代码可能比一些代码长,我承认可能有更简单的方法可以做到这一点,但是我会做三件事:

  1. 保持你的交叉应用与节点,因为节点是有用的,因为它会重复你需要依靠的行。但是,我会为您用于节点的名称添加一个人工标志。然后我将使用节点将两个选择语句联合在一起。
  2. 然后,我将使用嵌套选择作为 from 语句,然后根据我刚刚设置的标志使用窗口函数确定行号。
  3. 然后我会再次嵌套它,然后使用与行号的 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
于 2013-06-14T19:54:54.740 回答