【问题标题】:Correct exact Element counting from xml with Apply method使用 Apply 方法从 xml 更正准确的元素计数
【发布时间】:2020-10-05 10:52:41
【问题描述】:

如果在提取 APPLY 方法中使用,如何获取元素的行号(这里是 SpatialElement)? 主要问题是目前的代码方法计算每一行(不仅仅是SpatialElement的数量)

这里是代码 (应用方法使用了两次)

声明@xml xml = '

<Parcels>
 <Parcel ID="1">
   <EntitySpatial>
     <SpatialElement>
         <SpelementUnit  PointNum="1">
          <Ordinate X="100.1" Y="-100.1" />
         </SpelementUnit>
         <SpelementUnit  PointNum="2">
          <Ordinate X="100.2" Y="-100.2" />
         </SpelementUnit> 
     </SpatialElement>
     <SpatialElement>
         <SpelementUnit  PointNum="2">
          <Ordinate X="100.3" Y="-100.3" />
         </SpelementUnit>
         <SpelementUnit  PointNum="2">
          <Ordinate X="100.4" Y="-100.4" />
          </SpelementUnit>
         <SpelementUnit  PointNum="3">
          <Ordinate X="100.5" Y="-100.5" />
         </SpelementUnit> 
     </SpatialElement>            
   </EntitySpatial>
 </Parcel>

 <Parcel ID="2">
   <EntitySpatial>
     <SpatialElement>    
         <SpelementUnit  PointNum="1">
          <Ordinate X="200.1" Y="-200.1" />
         </SpelementUnit>
         <SpelementUnit  PointNum="2">
          <Ordinate X="200.2" Y="-200.2" /> 
         </SpelementUnit> 
     </SpatialElement>
   </EntitySpatial>
 </Parcel>
</Parcels>

'

 INSERT INTO [BD].[dbo].[RowNumber_For_SpatialElement] (        
 
Parcel_ID

-- RN

,SpatialElement_RowLabel
,SpatialElement_RN 

--

,PointNum
,Ordinate_X
,Ordinate_Y

  )

SELECT 

base.value('(@ID)[1]', 'VARCHAR(1000)')

--------- RowNumber counting

,outr.value('.', 'varchar(1000)') as SpatialElement_RowLabel,
   row_number() over(order by base) as SpatialElement_RN

----------

,outr2.value('(@PointNum)[1]', 'NVARCHAR(1000)')
,outr2.value('(*:Ordinate/@X)[1]', 'NVARCHAR(1000)')
,outr2.value('(*:Ordinate/@Y)[1]', 'NVARCHAR(1000)')

FROM @xml.nodes('*:Parcels/*:Parcel') as x(base)

OUTER APPLY base.nodes('*:EntitySpatial/*:SpatialElement') B(outr) 
OUTER APPLY base.nodes('*:EntitySpatial/*:SpatialElement/*:SpelementUnit') C(outr2) 

期望的输出 有点儿 (主要是在一个Parcel 元素或Parcels 中为每个SpatialElement 保持RowNumber (RN) 唯一)

Parcel_ID  SpatialElement_RowLabel   SpatialElement_RN    PointNum   Ordinate_X  Ordinate_Y          
      1                                  1                   1        100.1      -100.1
      1                                  1                   2        100.2      -100.2
      1                                  1                   3        100.3      -100.3

      1                                  2                   1        100.4      -100.4
      1                                  2                   2        100.5      -100.5

      2                                  1(or3)              1        200.1      -200.1
      2                                  1(or3)              2        200.2      -200.2

注意

  • 如果SpatialElementParcel中的单个序列-->EntitySpatial表中的记录数是相同的xml记录数。但是如果有更多的1,就会发生乘法。但在这种情况下,没关系(而且可能是不可避免的)。

  • 即使它是 SpatialElement 的属性,如“NumberOfRecod”应用方法,也会为所有点交叉混合所有这些属性。

  • 作为期望的结果,它可能是可接受的 RowNumber 变体计数 Parcel 内的所有找到的元素或 Parcels 元素内的连续计数(后者可能更可取)。

  • (可选)避免出现 RowLable 列(它具有空值)但将计数保持在 SpatialElement_RN

【问题讨论】:

    标签: sql-server xml tsql xquery


    【解决方案1】:

    请尝试以下解决方案。

    对原始 SQL 的修改:

    • 删除了命名空间通配符。
    • 修改了OUTER APPLY 子句及其 XPath 表达式以模拟一对多关系。
    • 使用了DENSE_RANK() 函数。

    SQL

    DECLARE @xml XML = 
    N'<Parcels>
        <Parcel ID="1">
            <EntitySpatial>
                <SpatialElement>
                    <SpelementUnit PointNum="1">
                        <Ordinate X="100.1" Y="-100.1"/>
                    </SpelementUnit>
                    <SpelementUnit PointNum="2">
                        <Ordinate X="100.2" Y="-100.2"/>
                    </SpelementUnit>
                </SpatialElement>
                <SpatialElement>
                    <SpelementUnit PointNum="1">
                        <Ordinate X="100.3" Y="-100.3"/>
                    </SpelementUnit>
                    <SpelementUnit PointNum="2">
                        <Ordinate X="100.4" Y="-100.4"/>
                    </SpelementUnit>
                    <SpelementUnit PointNum="3">
                        <Ordinate X="100.5" Y="-100.5"/>
                    </SpelementUnit>
                </SpatialElement>
            </EntitySpatial>
        </Parcel>
        <Parcel ID="2">
            <EntitySpatial>
                <SpatialElement>
                    <SpelementUnit PointNum="1">
                        <Ordinate X="200.1" Y="-200.1"/>
                    </SpelementUnit>
                    <SpelementUnit PointNum="2">
                        <Ordinate X="200.2" Y="-200.2"/>
                    </SpelementUnit>
                </SpatialElement>
            </EntitySpatial>
        </Parcel>
    </Parcels>';
    
    SELECT base.value('@ID', 'VARCHAR(1000)') AS Parcel_ID
        , DENSE_RANK() OVER(ORDER BY outr) as SpatialElement_RN
        ,outr2.value('@PointNum', 'NVARCHAR(1000)') AS PointNum
        ,outr2.value('(Ordinate/@X)[1]', 'NVARCHAR(1000)') AS Ordinate_X
        ,outr2.value('(Ordinate/@Y)[1]', 'NVARCHAR(1000)') AS Ordinate_Y
    FROM @xml.nodes('Parcels/Parcel') as x(base)
        OUTER APPLY base.nodes('EntitySpatial/SpatialElement') AS B(outr)
        OUTER APPLY outr.nodes('SpelementUnit') AS C(outr2);
    

    输出

    +-----------+-------------------+----------+------------+------------+
    | Parcel_ID | SpatialElement_RN | PointNum | Ordinate_X | Ordinate_Y |
    +-----------+-------------------+----------+------------+------------+
    |         1 |                 1 |        1 |      100.1 |     -100.1 |
    |         1 |                 1 |        2 |      100.2 |     -100.2 |
    |         1 |                 2 |        1 |      100.3 |     -100.3 |
    |         1 |                 2 |        2 |      100.4 |     -100.4 |
    |         1 |                 2 |        3 |      100.5 |     -100.5 |
    |         2 |                 3 |        1 |      200.1 |     -200.1 |
    |         2 |                 3 |        2 |      200.2 |     -200.2 |
    +-----------+-------------------+----------+------------+------------+
    

    【讨论】:

    • 还有一个问题。修改这段代码是否容易让每个节点中的RN从1开始计数(这里是指在每个Parcel节点内)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多