我有一个带有以下结构的表AREAGEOMETRY:
+-----------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+----------+------+-----+---------+-------+
| AREAGEOMETRY_ID | int(11) | NO | PRI | NULL | |
| AreaManagerId | int(11) | YES | | NULL | |
| AreaId | text | YES | | NULL | |
| EndDateArea | datetime | YES | | NULL | |
| StartDateArea | datetime | YES | | NULL | |
| AreaGeometryTxt | text | YES | | NULL | |
+-----------------+----------+------+-----+---------+-------+
它包含停车区的数据。现在我要做的是选择边界框内的所有行。
边界框可能如下:
LatLngBounds{southwest=lat/lng: (52.35631327204287,4.881156384944916), northeast=lat/lng: (52.38006384519922,4.913054890930653)}
我想出了以下查询:
SELECT * FROM AREAGEOMETRY WHERE ST_OVERLAPS(GeomFromText(AreaGeometryTxt), GeomFromText('LINESTRING(52.35631327204287 4.881156384944916, 52.38006384519922 4.881156384944916, 52.38006384519922 4.913054890930653, 52.35631327204287 4.913054890930653, 52.35631327204287 4.881156384944916)'))
然而它似乎返回表中的所有行,我不知道这里出了什么问题。 也许有人可以指出我正确的方向。
编辑:
例如,它返回此行:
# AREAGEOMETRY_ID, AreaManagerId, AreaId, EndDateArea, StartDateArea, AreaGeometryTxt
493, 299, 8721, 0000-00-00 00:00:00, 0000-00-00 00:00:00, POLYGON ((6.071624141 51.927465383, 6.071167939 51.927755315, 6.073816653 51.928513734, 6.07434586 51.928376592, 6.072239751 51.927748706, 6.072269225 51.927414931, 6.071624141 51.927465383))
不应该这样。
EDIT2: 一些可能的视口及其结果:
视口1:
LatLngBounds{southwest=lat/lng: (52.367693923958065,6.981273405253887), northeast=lat/lng: (52.3812037840295,6.99942022562027)}
查询:
SELECT * FROM AREAGEOMETRY WHERE ST_CONTAINS(GeomFromText('LINESTRING(52.367693923958065 6.981273405253887, 52.3812037840295 6.981273405253887, 52.3812037840295 6.99942022562027, 52.367693923958065 6.99942022562027, 52.367693923958065 6.981273405253887)'), GeomFromText(AreaGeometryTxt));
预期结果:返回0行
实际结果:返回0行
视口2:
LatLngBounds{southwest=lat/lng: (52.20765248996001,6.881230026483536), northeast=lat/lng: (52.23028692988024,6.911527253687382)}
查询:
SELECT * FROM AREAGEOMETRY WHERE ST_CONTAINS(GeomFromText('LINESTRING(52.20765248996001 6.881230026483536, 52.23028692988024 6.881230026483536, 52.23028692988024 6.911527253687382, 52.20765248996001 6.911527253687382, 52.20765248996001 6.881230026483536)'), GeomFromText(AreaGeometryTxt));
预期结果:返回约25行
实际结果:返回0行
另一个查询相同的视口:
SELECT * FROM AREAGEOMETRY WHERE ST_Overlaps(GeomFromText('LINESTRING(52.20765248996001 6.881230026483536, 52.23028692988024 6.881230026483536, 52.23028692988024 6.911527253687382, 52.20765248996001 6.911527253687382, 52.20765248996001 6.881230026483536)'), GeomFromText(AreaGeometryTxt));
预期结果:返回约25行
实际结果:返回1000行(受MySQL Workbench限制)
编辑3: 以下查询返回我想要的内容:
SELECT * FROM AREAGEOMETRY WHERE ST_Intersects(GeomFromText('Polygon((6.881230026483536 52.20765248996001, 6.881230026483536 52.23028692988024, 6.911527253687382 52.20765248996001, 6.881230026483536 52.20765248996001))'), GeomFromText(AreaGeometryTxt));
好像我混合了Lat / Lng并且参数的顺序错误。
答案 0 :(得分:2)
您应该使用包含或相交,具体取决于您是否要包含边框上的对象,或者是否要完全包含。 但是,你的主要问题是你的几何形状是错误的,如果你看Contains documentation你会看到它是包含(g1,g2)如果g1包含g2则返回1,所以你会想要把你的边界框放在第一位。
SELECT * FROM AREAGEOMETRY WHERE ST_CONTAINS(ST_GeomFromText('LINESTRING(52.35631327204287 4.881156384944916, 52.38006384519922 4.881156384944916, 52.38006384519922 4.913054890930653, 52.35631327204287 4.913054890930653, 52.35631327204287 4.881156384944916)'), ST_GeomFromText(AreaGeometryTxt));
您可能还需要考虑将AreaGeometryTxt存储为几何体而不是文本,因为这会给您带来两个好处:
然后,您可以在其上放置spatial index,这会随着表格大小的增长而提高查询时间。
您将避免每个查询的GeomFromText转换开销,与第1点一起,将阻止每次执行全表扫描。
编辑:我运行了以下查询,使用了您不应该返回的行以及原始的lat / lon边界框:
select ST_Overlaps(ST_GeomFromText('POLYGON ((6.071624141 51.927465383, 6.071167939 51.927755315, 6.073816653 51.928513734, 6.07434586 51.928376592, 6.072239751 51.927748706, 6.072269225 51.927414931, 6.071624141 51.927465383))'),
ST_GeomFromText('POLYGON ((4.881156384944916 52.35631327204287, 4.881156384944916 52.38006384519922, 4.913054890930653 52.38006384519922, 4.913054890930653 52.35631327204287, 4.881156384944916 52.35631327204287))'));
此查询为overlaps
,intersects
和contains
返回0(false)。