使用多边形列表过滤点列表
Filter list of points using list of Polygons
给定一个点列表和一个多边形列表。您如何 return 列表中任何多边形中的点列表(原始点列表的子集)
我删除了示例 table 中的其他列以简化操作
分Table:
| Longitude| Latitude |
|----------|-----------|
| 7.07491 | 51.28725 |
| 3.674765 | 51.40205 |
| 6.049105 | 51.86624 |
位置多边形 Table:
| LineString |
|----------------------|
| CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.20 47.45, -122.81 47.0, -122.942505 46.687131 ... |
| MULTIPOLYGON (((-110.3086 24.2154, -110.30842 24.2185966, -110.3127...
如果我有来自 LocationPolygons 的行 table 我可以做类似
DECLARE @homeLocation geography;
SET @homeLocation = (select top 1 GEOGRAPHY::STGeomFromText(LineString, 4326)
FROM LocationPolygon where LocationPolygonId = '123abc')
select Id, Longitude, Latitude, @homeLocation.STContains(geography::Point(Latitude, Longitude, 4326))
as IsInLocation from Points PointId in (1, 2, 3,)
这将 return 我想要的格式如下所示。然而,这仅适用于列表中的一个位置
| Id | Longitude| Latitude | IsInLocation |
|----|----------|-----------|--------------|
| 1 | 7.07491 | 51.28725 | 0 |
| 2 | 3.674765 | 51.40205 | 1 |
| 3 | 6.049105 | 51.86624 | 0 |
如何处理具有多行 LocationPolygon table 的场景?
我想知道
- 如果任何点在任何位置多边形中?
- 它们位于哪个特定位置的多边形中?或者如果它们位于多个多边形中。
问题2更多的是题外话。有人可以帮忙吗?
更新 #1
回应@Ben-Thul 的回答。
不幸的是,我没有 access/permission 来对原始 table 进行更改,我可以请求访问权限,但不确定是否会提供。所以不确定我是否能够添加列或创建索引。虽然我可以在存储过程中创建临时 tables,但我也许可以用这种方式测试你的解决方案
我偶然发现了如下答案,但有点担心使用交叉连接对性能的影响。
WITH cte AS (
select *, (GEOGRAPHY::STGeomFromText(LineString, 4326)).STContains(geography::Point(Latitude, Longitude, 4326)) as IsInALocation from
(
select Longitude, Latitude from Points nolock
) a cross join (
select LineString FROM LocationPolygons nolock
) b
)
select * from cte where IsInALocation = 1
显然,最好查看查询计划,但我偶然发现的解决方案与您的解决方案基本相同吗?有没有我遗漏的潜在问题。对此表示歉意,但我的 sql 不是很好。
问题 1 应该还不错。首先,一些设置:
alter table dbo.Points add Point as (GEOGRAPHY::Point(Latitude, Longitude, 4326));
create spatial index IX_Point on dbo.Points (Point) with (online = on);
alter table dbo.LocationPolygon add Polygon as (GEOGRAPHY::STGeomFromText(LineString, 4326));
create spatial index IX_Polygon on dbo.LocationPolygon (Polygon) with (online = on);
这将在每个 table 类型的 geography
上创建一个计算列,上面有一个空间索引。
从那里,你应该能够做这样的事情:
select pt.ID,
pt.Longitude,
pt.Latitude,
coalesce(pg.IsInLocation, 0) as IsInLocation
from Points as pt
outer apply (
select top(1) 1 as IsInLocation
from dbo.LocationPolygon as pg
where pg.Polygon.STContains(p.Point) = 1
) as pg;
在这里,您正在 select 点 table 的每一行并使用 outer apply
查看是否有任何多边形包含该点。如果有一个(哪个无关紧要),该查询将 return 结果集中的 1 和冒泡备份到驱动 select.
要将其扩展到问题 2,您可以从 outer apply
中删除 top()
并将其 return 来自多边形 table 的 ID 或任何您想要的 ID想。请注意,它会 return 每个包含点的多边形一行,可能会改变结果集的基数!
给定一个点列表和一个多边形列表。您如何 return 列表中任何多边形中的点列表(原始点列表的子集)
我删除了示例 table 中的其他列以简化操作
分Table:
| Longitude| Latitude |
|----------|-----------|
| 7.07491 | 51.28725 |
| 3.674765 | 51.40205 |
| 6.049105 | 51.86624 |
位置多边形 Table:
| LineString |
|----------------------|
| CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.20 47.45, -122.81 47.0, -122.942505 46.687131 ... |
| MULTIPOLYGON (((-110.3086 24.2154, -110.30842 24.2185966, -110.3127...
如果我有来自 LocationPolygons 的行 table 我可以做类似
DECLARE @homeLocation geography;
SET @homeLocation = (select top 1 GEOGRAPHY::STGeomFromText(LineString, 4326)
FROM LocationPolygon where LocationPolygonId = '123abc')
select Id, Longitude, Latitude, @homeLocation.STContains(geography::Point(Latitude, Longitude, 4326))
as IsInLocation from Points PointId in (1, 2, 3,)
这将 return 我想要的格式如下所示。然而,这仅适用于列表中的一个位置
| Id | Longitude| Latitude | IsInLocation |
|----|----------|-----------|--------------|
| 1 | 7.07491 | 51.28725 | 0 |
| 2 | 3.674765 | 51.40205 | 1 |
| 3 | 6.049105 | 51.86624 | 0 |
如何处理具有多行 LocationPolygon table 的场景?
我想知道
- 如果任何点在任何位置多边形中?
- 它们位于哪个特定位置的多边形中?或者如果它们位于多个多边形中。
问题2更多的是题外话。有人可以帮忙吗?
更新 #1 回应@Ben-Thul 的回答。
不幸的是,我没有 access/permission 来对原始 table 进行更改,我可以请求访问权限,但不确定是否会提供。所以不确定我是否能够添加列或创建索引。虽然我可以在存储过程中创建临时 tables,但我也许可以用这种方式测试你的解决方案
我偶然发现了如下答案,但有点担心使用交叉连接对性能的影响。
WITH cte AS (
select *, (GEOGRAPHY::STGeomFromText(LineString, 4326)).STContains(geography::Point(Latitude, Longitude, 4326)) as IsInALocation from
(
select Longitude, Latitude from Points nolock
) a cross join (
select LineString FROM LocationPolygons nolock
) b
)
select * from cte where IsInALocation = 1
显然,最好查看查询计划,但我偶然发现的解决方案与您的解决方案基本相同吗?有没有我遗漏的潜在问题。对此表示歉意,但我的 sql 不是很好。
问题 1 应该还不错。首先,一些设置:
alter table dbo.Points add Point as (GEOGRAPHY::Point(Latitude, Longitude, 4326));
create spatial index IX_Point on dbo.Points (Point) with (online = on);
alter table dbo.LocationPolygon add Polygon as (GEOGRAPHY::STGeomFromText(LineString, 4326));
create spatial index IX_Polygon on dbo.LocationPolygon (Polygon) with (online = on);
这将在每个 table 类型的 geography
上创建一个计算列,上面有一个空间索引。
从那里,你应该能够做这样的事情:
select pt.ID,
pt.Longitude,
pt.Latitude,
coalesce(pg.IsInLocation, 0) as IsInLocation
from Points as pt
outer apply (
select top(1) 1 as IsInLocation
from dbo.LocationPolygon as pg
where pg.Polygon.STContains(p.Point) = 1
) as pg;
在这里,您正在 select 点 table 的每一行并使用 outer apply
查看是否有任何多边形包含该点。如果有一个(哪个无关紧要),该查询将 return 结果集中的 1 和冒泡备份到驱动 select.
要将其扩展到问题 2,您可以从 outer apply
中删除 top()
并将其 return 来自多边形 table 的 ID 或任何您想要的 ID想。请注意,它会 return 每个包含点的多边形一行,可能会改变结果集的基数!