使用 XQuery 正确旋转 XML 列

JF *_*dry 3 xml pivot xquery sql-server-2014

我想透视 SQL XML 列的属性和值,并以有序的列和行格式显示它。

首先,这是 XML 列在 SQL 中的样子:

<Model xmlns:dsc="ModelDescriptive" xmlns:draw="ModelDraw" xmlns:display="Display" xmlns:thd="Model3D">
  <dsc:Model name="15DE">
    <dsc:Defs>
      <dsc:Materials>
        <dsc:Material ref="E-HD-AnoAno" baseRef="E-HD" type="rod" productionGroup="OPTION" />
        <dsc:Material ref="E-3L44A-CLEAR" baseRef="E-3L44A" type="piece" productionGroup="OPTION" />
        <dsc:Material ref="R-TH01" baseRef="R-TH-TH" type="rod" productionGroup="ASSEMBLY" />
        <dsc:Material ref="M-TH05" baseRef="M-TH" type="meter" productionGroup="MOLDING" />
      </dsc:Materials>
    </dsc:Defs>
  </dsc:Model>
</Model>
Run Code Online (Sandbox Code Playgroud)

...这是我的查询:

 SELECT
      x.y.value('local-name(..)', 'VARCHAR(MAX)') ParentElementName
     ,x.y.value('local-name(.)', 'VARCHAR(MAX)') Attribut
     ,x.y.value('.', 'VARCHAR(MAX)') Value
     ,Row_number() Over(Partition by x.y.value('local-name(..)', 'VARCHAR(MAX)') order by x.y.value('local-name(..)', 'VARCHAR(MAX)') ASC)  as rn
 FROM @xmlDescriptive.nodes('//*[text()], //@*') AS x(y)
 WHERE x.y.value('local-name(..)', 'VARCHAR(MAX)')= 'Material'
 ORDER BY x.y.value('local-name(..)', 'VARCHAR(MAX)')
Run Code Online (Sandbox Code Playgroud)

我使用XQueryNodes方法得到了一个有趣的结果,并且只对材料清单 (BOM) 中的材料进行过滤。

但是,我想以标准化的方式呈现数据。

我得到的第一个结果是这样的:

在此处输入图片说明

然后我转换这个结果以使用 Pivot 方法旋转它。这是我尝试透视我的信息的方法:

 SELECT [ref], [baseRef], [type], [productionGroup]
 FROM 
 (
     SELECT
          x.y.value('local-name(..)', 'VARCHAR(MAX)') ParentElementName
         ,x.y.value('local-name(.)', 'VARCHAR(MAX)') Attribut
         ,x.y.value('.', 'VARCHAR(MAX)') Valeur
         ,CAST(Row_number() Over(Partition by x.y.value('local-name(.)', 'VARCHAR(MAX)') order by x.y.value('local-name(..)', 'VARCHAR(MAX)') ASC) as varchar(10)) as rn
     FROM @xmlDescriptive.nodes('//@*') AS x(y)
     WHERE x.y.value('local-name(..)', 'VARCHAR(MAX)')= 'Material'
    
 ) d
 pivot
 (
   max(Valeur)
   FOR Attribut in ([ref], [baseRef], [type], [productionGroup])
 ) piv 
Run Code Online (Sandbox Code Playgroud)

我发现我的结果是无序的。列ref与我的baseReftypeproductGroup列不匹配:

在此处输入图片说明

我有点困惑。我想以这种方式格式化我的结果,但已订购。我的推理有什么问题?

我希望我的结果如下所示:

在此处输入图片说明

Mik*_*son 5

我可能错过了您的问题的重点,但这是我为获得您正在寻找的结果而要做的事情。

with xmlnamespaces('ModelDescriptive' as dsc)
select M.X.value('@ref', 'varchar(max)') as ref,
       M.X.value('@baseRef', 'varchar(max)') as baseRef,
       M.X.value('@type', 'varchar(max)') as type,
       M.X.value('@productionGroup', 'varchar(max)') as productionGroup
from @xmlDescriptive.nodes('//dsc:Material') as M(X);
Run Code Online (Sandbox Code Playgroud)

您对local-name()和 的使用//*[text()], //@*'建议您想要某种通用数据透视表,但您Material在查询中使用和硬编码的属性名称,所以我不知道您为什么走那条路。