Укажите порядок, который использует CollectionAggregate - PullRequest
2 голосов
/ 21 марта 2019

Я применяю порядок, в котором геометрия содержится в GEOMETRYCOLLECTION, объединяя wkt и используя STUFF с ORDER BY

(я использую SQL Server 2016, в противном случае я бы использовал STRING_AGG )

DECLARE @OrderedGeometryList TABLE  
(  
    [GroupId] INT,
    [Geometry] GEOMETRY,
    [Order] INT
)  


INSERT @OrderedGeometryList
VALUES 
     (1, 'LINESTRING(3 3, 4 4)', 3)
    ,(1, 'LINESTRING(0 0, 1 1)', 1)
    ,(1, 'LINESTRING(1 1, 2 2)', 2)
    ,(2, 'POINT(35453 141)', 2)
    ,(2, 'MULTILINESTRING((0 0, 1 1),(2 2, 3 3))', 1)

Тогда

;WITH Grouped AS (
    SELECT 
        [GroupId]
        ,Geometry::STGeomCollFromText(
            'GEOMETRYCOLLECTION(' + 
                STUFF((
                    SELECT ',' + [Geometry].ToString()
                    FROM @OrderedGeometryList t2
                    WHERE t1.[GroupId] = t2.[GroupId] 
                    ORDER BY [Order]
                    FOR XML PATH ('')
                ), 1, 1, '')
            + ')', MAX([Geometry].STSrid)
        ) as [Geometry]
    FROM @OrderedGeometryList t1
    GROUP BY [GroupId]
)


SELECT GroupId, Geometry.ToString() as WKT
FROM Grouped

Выдает:

GroupId WKT
1   GEOMETRYCOLLECTION (LINESTRING (0 0, 1 1), LINESTRING (1 1, 2 2), LINESTRING (3 3, 4 4))
2   GEOMETRYCOLLECTION (MULTILINESTRING ((0 0, 1 1), (2 2, 3 3)), POINT (35453 141))

Обратите внимание, как порядок сбора (слева направо) соответствует порядку, указанному в таблице. Это эффект, которого я добиваюсь, но мне любопытно, есть ли более чистый способ сделать это.

Я подумал о том, чтобы написать свой собственный агрегат CLR, а затем использовать OVER() с ORDER BY, но, похоже, это не поддерживается Можно ли использовать определенные пользователем агрегаты (clr) с оконными функциями (более)?

1 Ответ

2 голосов
/ 21 марта 2019

Вы можете использовать OFFSET в подзапросе для упорядочивания строк.

SELECT Geometry::CollectionAggregate([Geometry]).ToString() 
FROM 
    (SELECT * FROM @OrderedGeometryList ORDER BY [GroupId], [Order] OFFSET 0 ROWS) T
GROUP BY [GroupId]

Результат:

GEOMETRYCOLLECTION (LINESTRING (0 0, 1 1), LINESTRING (1 1, 2 2), LINESTRING (3 3, 4 4))
GEOMETRYCOLLECTION (MULTILINESTRING ((0 0, 1 1), (2 2, 3 3)), POINT (35453 141))
...