代码之家  ›  专栏  ›  技术社区  ›  Jeremy

如何获取祖先元素在父元素中的位置/索引

  •  0
  • Jeremy  · 技术社区  · 5 年前

    我得到了如下的xml:

    <items>
        <item>
          <itemproperty>true</itemproperty>
          <details>
            <details>
              <ID Type="z" Value="1"/>
              <ID Type="w" Value="2"/>
            </details>
          </Locations>
        </item>
        <item>
          <itemproperty>true</itemproperty>
          <details>
            <details>
              <ID Type="a" Value="3"/>
              <ID Type="b" Value="4"/>
            </details>
          </Locations>
        </item>
    </items>
    

    我想产生如下输出:

    ItemIndex    DetailIDType     DetailIDValue
    1            z                1
    1            w                2
    2            a                3
    2            b                4
    

    我从/items/item/details/detail/ID节点进行查询,并尝试找出祖先item元素的位置/索引。我可以得到项目元素的总数,但我很难找到项目元素的位置。在所有情况下,它都不会返回正确的索引/位置值:

    SELECT DISTINCT
        [TestGetItemElementName] = IDs.id.value('fn:local-name(./../../..)', 'varchar(50)')
        ,[TestGetItemElementCount] = IDs.id.value('count(/items/item)', 'int')
        ,[ItemIndexTest1] = IDs.id.value('for $i in ./../../.. return count(/items/item/*[. << $i]) + 1', 'int')
        ,[ItemIndexTest2] = IDs.id.value('for $i in . return count(../*[. << $i]) + 1', 'int')
    
        ,[DetailIDType] = convert(VARCHAR(256), IDs.id.query('data(./@Type)')) 
        ,[DetailIDValue] = convert(VARCHAR(256), IDs.id.query('data(./@Value)'))
    FROM 
        @x.nodes('/Recipients/Recipient/Locations/Location/ID') AS IDs(id)
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   AlwaysLearning    5 年前

    尽量避免使用父轴( .. parent::node() )在XPath查询中,它可能是一个严重的性能杀手。

    你可以通过使用 DENSE_RANK() 提供自动编号的 item 包含以下代码的节点。。。

    declare @x xml = N'<items>
        <item>
          <itemproperty>true</itemproperty>
          <Locations>
            <details>
              <ID Type="z" Value="1"/>
              <ID Type="w" Value="2"/>
            </details>
          </Locations>
        </item>
        <item>
          <itemproperty>true</itemproperty>
          <Locations>
            <details>
              <ID Type="a" Value="3"/>
              <ID Type="b" Value="4"/>
            </details>
          </Locations>
        </item>
    </items>';
    
    select
      dense_rank() over (partition by items order by item) as ItemIndex
      ,details.value('@Type', N'nvarchar(256)') as DetailIDType
      ,details.value('@Value', N'nvarchar(256)') as DetailIDValue
    from @x.nodes('//items') nodes1(items)
    cross apply items.nodes('item') nodes2(item)
    cross apply item.nodes('Locations/details/ID') nodes3(details);
    

    结果如下:

    项目索引 DetailIDType DetailIDValue
    1. Z 1.
    1. W 2.
    2. A. 3.
    2. B 4.
        2
  •  0
  •   Yitzhak Khabinsky    5 年前

    我看到你试着用 节点比较 接线员去接电话 项目索引 列值。下面是如何正确地做这件事。

    SQL

    DECLARE @x XML = 
    N'<items>
        <item>
          <itemproperty>true</itemproperty>
          <Locations>
            <details>
              <ID Type="z" Value="1"/>
              <ID Type="w" Value="2"/>
            </details>
          </Locations>
        </item>
        <item>
          <itemproperty>true</itemproperty>
          <Locations>
            <details>
              <ID Type="a" Value="3"/>
              <ID Type="b" Value="4"/>
            </details>
          </Locations>
        </item>
    </items>';
    
    SELECT c.value('for $i in . return count(/items/item[. << $i])', 'INT') AS ItemIndex
        , c.value('@Type', 'VARCHAR(20)') as DetailIDType
        , c.value('@Value', 'INT') as DetailIDValue
    FROM @x.nodes('/items/item/Locations/details/ID') AS t(c);
    

    输出

    +-----------+--------------+---------------+
    | ItemIndex | DetailIDType | DetailIDValue |
    +-----------+--------------+---------------+
    |         1 | z            |             1 |
    |         1 | w            |             2 |
    |         2 | a            |             3 |
    |         2 | b            |             4 |
    +-----------+--------------+---------------+
    
    推荐文章