在mssql中查询XML节点

在mssql中查询XML节点,sql,sql-server,xml,Sql,Sql Server,Xml,我有以下XML记录 <row> <c1>BUSINESS.HOME</c1> <c1 m="2">PAYMENTS.HOME</c1> <c1 m="3">DEPARTMENT.PAGE</c1> <c1 m="4">SECTION.HOME</c1> <c1 m="5">ABOUT.HOME</c1> <c2>Our Busi

我有以下XML记录

<row>
  <c1>BUSINESS.HOME</c1>
  <c1 m="2">PAYMENTS.HOME</c1>
  <c1 m="3">DEPARTMENT.PAGE</c1>
  <c1 m="4">SECTION.HOME</c1>
  <c1 m="5">ABOUT.HOME</c1>

  <c2>Our Business</c2>
  <c2 m="1" s="2">Businesul nostru</c2>
  <c2 m="2">Payment Services</c2>
  <c2 m="2" s="2">Plati</c2>
  <c2 m="3">Department Operations</c2>
  <c2 m="3" s="2">Departamente</c2>
  <c2 m="4">Section Operations</c2>
  <c2 m="4" s="2">Sectiuni</c2>
  <c2 m="5">ABOUT</c2>
  <c2 m="5" s="2">Despre</c2>

  <c6>2</c6>
  <c10>GB0010001</c10>
  <c11>1</c11>
</row>
C1中的每个值和C2中相应的第一个值

我试过这样交叉应用:

select t.p.query('.').value('data(./c2)[1]', 'varchar(max)') c2
from table_name 
cross apply XMLRECORD.nodes('(/row/c2)') t(p)
where ID  = 'HOME.PAGE'
但不知道如何进一步排除外语并包含C1标记。

这有点“难看”,因为必须在
NULL
上匹配
NULL
,然而,这就是我如何实现您的目标:

DECLARE @XML xml = '
<row>
  <c1>BUSINESS.HOME</c1>
  <c1 m="2">PAYMENTS.HOME</c1>
  <c1 m="3">DEPARTMENT.PAGE</c1>
  <c1 m="4">SECTION.HOME</c1>
  <c1 m="5">ABOUT.HOME</c1>

  <c2>Our Business</c2>
  <c2 m="1" s="2">Businesul nostru</c2>
  <c2 m="2">Payment Services</c2>
  <c2 m="2" s="2">Plati</c2>
  <c2 m="3">Department Operations</c2>
  <c2 m="3" s="2">Departamente</c2>
  <c2 m="4">Section Operations</c2>
  <c2 m="4" s="2">Sectiuni</c2>
  <c2 m="5">ABOUT</c2>
  <c2 m="5" s="2">Despre</c2>

  <c6>2</c6>
  <c10>GB0010001</c10>
  <c11>1</c11>
</row>';

SELECT c1.value('(./text())[1]','varchar(15)') AS [NAME],
       c2.value('(./text())[1]','varchar(15)') AS LABEL
FROM @XML.nodes('row/c1') c1(c1)
     JOIN @XML.nodes('row/c2') c2(c2) ON (c1.value('@m','int') = c2.value('@m','int') AND c2.value('@s','int') IS NULL)
                                      OR (c1.value('@m','int') IS NULL AND c2.value('@m','int') IS NULL);
DECLARE@XML='XML'
商务之家
家
DEPARTMENT.PAGE
第1节主页
关于家
我们的生意
生意兴隆
支付服务
普拉蒂
部门运作
部门
科室业务
科蒂乌尼
关于
暴君
2.
GB0010001
1.
';
选择c1.value(“(./text())[1]”,“'varchar(15)”作为[NAME],
c2.值('(./text())[1]','varchar(15')作为标签
来自@XML.nodes('row/c1')c1(c1)
连接上的@XML.nodes('row/c2')c2(c2)(c1.value('m','int')=c2.value('m','int'))和c2.value('s','int')为空)
或者(c1.value('@m','int')为空,c2.value('@m','int')为空);

您已经有了一个有效的方法。那很好

我只想添加一个性能更好的替代方案

DECLARE @XML xml = '
<row>
  <c1>BUSINESS.HOME</c1>
  <c1 m="2">PAYMENTS.HOME</c1>
  <c1 m="3">DEPARTMENT.PAGE</c1>
  <c1 m="4">SECTION.HOME</c1>
  <c1 m="5">ABOUT.HOME</c1>

  <c2>Our Business</c2>
  <c2 m="1" s="2">Businesul nostru</c2>
  <c2 m="2">Payment Services</c2>
  <c2 m="2" s="2">Plati</c2>
  <c2 m="3">Department Operations</c2>
  <c2 m="3" s="2">Departamente</c2>
  <c2 m="4">Section Operations</c2>
  <c2 m="4" s="2">Sectiuni</c2>
  <c2 m="5">ABOUT</c2>
  <c2 m="5" s="2">Despre</c2>

  <c6>2</c6>
  <c10>GB0010001</c10>
  <c11>1</c11>
</row>';
简而言之:

  • 动态创建一个计数,返回一个从1到n的列表,其中n是
    元素的计数(如果您有一个数字表,请改用此表)
  • 使用Tally的
    Nmbr
    列,并使用
    sql:column()
    将其引入
    XQuery
    谓词。
    • 第一个
      .value()
      根据其位置调用
    • 第二个调用位置x2-1对应的值。如果没有“-1”,您将获得另一种语言
这是另一种方法,过滤不带
s
属性的
元素。在这种情况下,我们不需要计算位置x2-1:


你能告诉我们你的尝试吗?另外,你能解释一下你的逻辑吗。为什么
DEPARTMENT.PAGE
SECTION.HOME
ABOUT.HOME
都链接到
部门运营
我本希望
SECTION.HOME
链接到
部门运营
。将您的尝试放在问题中,而不是评论中。您是对的,我更正了结果。我将把这个问题添加到问题中。
DECLARE @XML xml = '
<row>
  <c1>BUSINESS.HOME</c1>
  <c1 m="2">PAYMENTS.HOME</c1>
  <c1 m="3">DEPARTMENT.PAGE</c1>
  <c1 m="4">SECTION.HOME</c1>
  <c1 m="5">ABOUT.HOME</c1>

  <c2>Our Business</c2>
  <c2 m="1" s="2">Businesul nostru</c2>
  <c2 m="2">Payment Services</c2>
  <c2 m="2" s="2">Plati</c2>
  <c2 m="3">Department Operations</c2>
  <c2 m="3" s="2">Departamente</c2>
  <c2 m="4">Section Operations</c2>
  <c2 m="4" s="2">Sectiuni</c2>
  <c2 m="5">ABOUT</c2>
  <c2 m="5" s="2">Despre</c2>

  <c6>2</c6>
  <c10>GB0010001</c10>
  <c11>1</c11>
</row>';
WITH Tally(Nmbr) AS(SELECT TOP(@Xml.value('count(/row/c1)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values )
SELECT @Xml.value('(/row/c1/text())[sql:column("Nmbr")][1]','nvarchar(250)') AS [NAME]
      ,@xml.value('(/row/c2/text())[sql:column("Nmbr")*2-1][1]','nvarchar(250)') AS [LABEL]
FROM Tally;
WITH Tally(Nmbr) AS(SELECT TOP(@Xml.value('count(/row/c1)','int')) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values )
SELECT @Xml.value('(/row/c1/text())[sql:column("Nmbr")][1]','nvarchar(250)') AS [NAME]
      ,@xml.value('(/row/c2[empty(@s)]/text())[sql:column("Nmbr")][1]','nvarchar(250)') AS [LABEL]
FROM Tally