Atrybut PointNum oznacza liczbę współrzędnych w łańcuchu. Łańcuch współrzędnych rozpoczyna się na 1 i kończy się w 1, jak również (wewnątrz każdego Parcel element).

Jednak w sekwencjach tych punktów jest jeszcze jedna wewnętrzna logika, który musi być wyjaśniony. Jest to logika pełnego współczynnika współrzędnych X i Y . Na przykład:

  • w sekwencji w ramach Parcel_id = 1 są równe współrzędne z pointnum 1 i 4, 5 i 7

  • W sekwencji w ramach Parcel_id = 2 są równe współrzędne z pointnum 1 и 3

Cel: Muszę również numerować te sub-łańcuchy. (w kolumnie SequenceNum)

KOD

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>
                <SpelementUnit PointNum="3">
                    <Ordinate X="100.3" Y="-100.3"/>
                </SpelementUnit>
                <SpelementUnit PointNum="4">
                    <Ordinate X="100.1" Y="-100.1"/>
                </SpelementUnit>

                <SpelementUnit PointNum="5">
                    <Ordinate X="100.5" Y="-100.5"/>
                </SpelementUnit>
                <SpelementUnit PointNum="6">
                    <Ordinate X="100.6" Y="-100.6"/>
                </SpelementUnit>
                <SpelementUnit PointNum="7">
                    <Ordinate X="100.5" Y="-100.5"/>
                </SpelementUnit>

                <SpelementUnit PointNum="8">
                    <Ordinate X="100.8" Y="-100.8"/>
                </SpelementUnit>
                <SpelementUnit PointNum="9">
                    <Ordinate X="100.9" Y="-100.9"/>
                </SpelementUnit>
                <SpelementUnit PointNum="10">
                    <Ordinate X="100.11" Y="-100.11"/>
                </SpelementUnit>
                <SpelementUnit PointNum="1">
                    <Ordinate X="100.1" Y="-100.1"/>
                </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>
                <SpelementUnit PointNum="3">
                    <Ordinate X="200.1"" Y="-200.1"/>
                </SpelementUnit>

                <SpelementUnit PointNum="4">
                    <Ordinate X="200.4" Y="-200.4"/>
                </SpelementUnit>
                <SpelementUnit PointNum="5">
                    <Ordinate X="200.5" Y="-200.5"/>
                </SpelementUnit>
                <SpelementUnit PointNum="1">
                    <Ordinate X="200.1" Y="-200.1"/>
                </SpelementUnit>

            </SpatialElement>
        </EntitySpatial>
    </Parcel>
</Parcels>';


SELECT base.value('@ID', 'VARCHAR(1000)') AS Parcel_ID
    , DENSE_RANK() OVER(ORDER BY outr) as SpatialElement_Count
    ,outr2.value('(Ordinate/@X)[1]', 'NVARCHAR(1000)') AS Ordinate_X
    ,outr2.value('(Ordinate/@Y)[1]', 'NVARCHAR(1000)') AS Ordinate_Y
    ,outr2.value('@PointNum', 'NVARCHAR(1000)') AS PointNum
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);

Pożądany wyjście (kolumna "seklencenum")

+-----------+----------------------+------------+------------+--------------------------+
| Parcel_ID | SpatialElement_Count | Ordinate_X | Ordinate_Y |  PointNum |  SequenceNum |
+-----------+----------------------+------------+------------+--------------------------+
|         1 |                    1 |      100.1 |     -100.1 |         1 |        1     |
|         1 |                    1 |      100.2 |     -100.2 |         2 |        1     |
|         1 |                    1 |      100.3 |     -100.3 |         3 |        1     |
|         1 |                    1 |      100.1 |     -100.1 |         4 |        1     |
|           |                      |            |            |           |              | 
|         1 |                    1 |      100.5 |     -100.5 |         5 |        2     |
|         1 |                    1 |      100.6 |     -100.6 |         6 |        2     |
|         1 |                    1 |      100.5 |     -100.5 |         7 |        2     |
|           |                      |            |            |           |              |  
|         1 |                    1 |      100.8 |     -100.8 |         8 |      null    |
|         1 |                    1 |      100.9 |     -100.9 |         9 |      null    |
|         1 |                    1 |     100.11 |    -100.11 |        10 |      null    |
|         1 |                    1 |      100.1 |     -100.1 |         1 |      null    |
|           |                      |            |            |           |              |  
|           |                      |            |            |           |              |  
|         2 |                    2 |      200.1 |     -200.1 |         1 |     1(or 3)  |
|         2 |                    2 |      200.2 |     -200.2 |         2 |     1(or 3)  |
|         2 |                    2 |      200.1 |     -200.1 |         3 |     1(or 3)  |
|           |                      |            |            |           |              |  
|         2 |                    2 |      200.4 |     -200.4 |         4 |      null    |
|         2 |                    2 |      200.5 |     -200.5 |         5 |      null    |
|         2 |                    2 |      200.1 |     -200.1 |         1 |      null    |
+-----------+----------------------+------------+------------+--------------------------+
0
XSLT-explorer 20 październik 2020, 19:42

1 odpowiedź

Najlepsza odpowiedź

To może ci pomóc. Należy pamiętać, że działa dla twojego przykładu, ale widzę, że w przypadku przypadków takich jak ...

  1. Więcej niż dwa równe współrzędne.
  2. Powiązane grupy współrzędnych.
  3. Skacze atrybutów pointnum (przerwy w sekwencji porządkowej)
WITH parseXml AS (
    SELECT
        base.value('@ID', 'VARCHAR(1000)') AS Parcel_ID,
        outr.value('for $se in . return count(//SpatialElement[. << $se]) + 1', 'INTEGER') AS SpatialElement_Count,
        outr2.value('for $o in . return count(../SpelementUnit[. << $o]) + 1', 'INTEGER') AS Ordinate_position,
        outr2.value('@PointNum', 'INTEGER') AS PointNum,
        outr2.value('(Ordinate/@X)[1]', 'NVARCHAR(100)') AS Ordinate_X,
        outr2.value('(Ordinate/@Y)[1]', 'NVARCHAR(100)') 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)
),
groups AS (
    SELECT
        Parcel_ID, Ordinate_X, Ordinate_Y,
        --Exclude last row in parcel_id
        MIN(CASE WHEN PointNum = Ordinate_position THEN Ordinate_position END) AS StartSequence,
        MAX(CASE WHEN PointNum = Ordinate_position THEN Ordinate_position END) AS EndSequence,
        ROW_NUMBER() OVER(PARTITION BY Parcel_ID
            ORDER BY MIN(CASE WHEN PointNum = Ordinate_position THEN Ordinate_position END)) AS SequenceNum
    FROM
        parseXml
    GROUP BY
        Parcel_ID, Ordinate_X, Ordinate_Y
    HAVING COUNT(*) > 1
)
SELECT
    ref.Parcel_ID, ref.SpatialElement_Count, ref.Ordinate_X, ref.Ordinate_Y, ref.PointNum,
    groups.SequenceNum
FROM
    parseXml ref
    LEFT JOIN groups
        ON groups.StartSequence <= ref.Ordinate_position
        AND groups.EndSequence >= ref.Ordinate_position
        AND groups.Parcel_ID = ref.Parcel_ID
ORDER BY
    ref.Parcel_ID, Ordinate_position;
1
Adán Bucio 21 październik 2020, 06:26