1

鉴于此 XML 片段(VIN 显然是伪造的)

<VehicleFeed>
  <Vehicle>
    <VIN>1234</VIN>
    <Equipment>
      <EquipmentDesc>1.1</EquipmentDesc>
      <EquipmentDesc>1.2</EquipmentDesc>
      <EquipmentDesc>1.3</EquipmentDesc>
    </Equipment>
  </Vehicle>
  <Vehicle>
    <VIN>2345</VIN>
    <Equipment>
      <EquipmentDesc>2.1</EquipmentDesc>
      <EquipmentDesc>2.2</EquipmentDesc>
      <EquipmentDesc>2.3</EquipmentDesc>
    </Equipment>
  </Vehicle>
</VehicleFeed>

What I really want is this result set

VIN  EquipmentDesc
---  -------------
1234 1.1
1234 1.2
1234 1.3
2345 2.1
2345 2.2
2345 2.3

我在名为@xdata 的var 中有xml 数据。下面的代码是我认为可行的,但它将所有设备值连接到单个数据列中,而不是将它们分成行。

select t.c.value('VIN[1]', 'varchar(20)') as VIN
     , t1.c1.value('.', 'varchar(80)') as EquipDesc
from @xdata.nodes('//VehicleFeed/Vehicle') as t(c)
cross apply t.c.nodes('Equipment') as t1(c1)

即,我得到

VIN  EquipmentDesc
---  -------------
1234 1.11.21.3
2345 2.12.22.3

我显然做错了什么,大概是交叉应用或描述数据的选择(或两者),但我不知道它是什么。看起来这很简单,但我没有看到。

4

2 回答 2

1

您可以使用更短的语句来实现相同的目的:

select t.c.value('../../VIN[1]', 'varchar(20)') as VIN
     , t.c.value('.', 'varchar(80)') as EquipDesc
from @xdata.nodes('/VehicleFeed/Vehicle/Equipment/EquipmentDesc') as t(c);
于 2013-10-13T18:52:36.023 回答
1

后来我明白了答案。我只需要添加更多级别的交叉应用以下降到 EquipmentDesc 元素 - 脑损伤,周六晚上编码。

cross apply t1.c1.nodes('EquipmentDesc') as t2(c2)

并使用选择设备描述值

, t2.c2.value('.', 'varchar(80)') as EquipDesc

我不经常使用交叉应用,当我调整一些现有代码时很容易忘记它的真正含义。对不起,如果我浪费了任何人的时间。

添加

最终查询(至少相关部分)

select t.c.value('VIN[1]', 'varchar(20)') as VIN
     , t2.c2.value('.', 'varchar(80)') as EquipDesc
from @xdata.nodes('//VehicleFeed/Vehicle') as t(c)
cross apply t.c.nodes('Equipment') as t1(c1)
cross apply t1.c1.nodes('EquipmentDesc') as t2(c2)
于 2013-10-13T00:02:06.317 回答