SQL如何按地理区域分组统计_关联经纬度范围与维度表

夏杰小哥_3401

夏杰小哥_3401

2026-05-07

386人浏览

原创

需用空间函数(如st_within)将经纬度转点后匹配多边形行政区,而非简单四舍五入;须确保坐标系一致、维度表含空间索引及合适颗粒度,否则会导致漏匹配或性能差。

sql如何按地理区域分组统计_关联经纬度范围与维度表

怎么用经纬度坐标匹配到行政区划维度表

核心是把原始数据里的 lat 和 lng 落到某个省/市/区的多边形范围内,不是简单四舍五入或取整。直接用 BETWEEN 做矩形框粗筛可以,但会漏掉边界弯曲区域(比如长三角某镇实际属江苏,却落在上海矩形框外)。

实操建议:

  • 先确保维度表(如 dim_region)有 geom 字段,类型为 POLYGON 或 GEOMETRY,且已建立空间索引(PostGIS 用 CREATE INDEX ON dim_region USING GIST(geom))
  • 原始表需转成点:PostGIS 中用 ST_Point(lng, lat)(注意顺序是经度在前),再用 ST_Within(point, region.geom) 判断是否在内
  • MySQL 8.0+ 可用 ST_Contains(region.geom, ST_Point(lng, lat)),但性能弱于 PostGIS,且必须确保 geom 是 SRID 4326
  • 如果没空间扩展,退而求其次:用最小外接矩形(MBR)预过滤——ST_Contains(ST_Envelope(region.geom), ST_Point(lng, lat)),再加业务规则兜底(如按城市中心点距离 fallback)

为什么 GROUP BY 区域字段后总数对不上

常见现象是:原始记录 10 万条,分组后 sum(count) 只有 9.2 万。根本原因不是 SQL 写错,而是坐标落在所有已知行政区划范围之外(海洋、边境无人区、坐标系不一致、或维度表本身缺失某些飞地)。

排查步骤:

  • 先查未匹配上的点:SELECT lat, lng FROM raw_data d LEFT JOIN dim_region r ON ST_Within(ST_Point(d.lng, d.lat), r.geom) WHERE r.id IS NULL LIMIT 100
  • 检查坐标系:原始数据若来自高德/百度,是 GCJ-02 或 BD-09,必须先纠偏转 WGS84(用对应 SDK 或开源库如 coordtransform),否则 ST_Point 构造的点位置偏差可达 500 米
  • 维度表若只含地级市,但你要统计到区县,就必然有“市辖区”未覆盖的街道数据——得确认维度表颗粒度是否匹配业务需求

如何让地理分组查询不慢到超时

空间 JOIN 天然比普通 JOIN 慢,尤其当原始表千万级、区域表上千个面时,没优化很容易 10 分钟不出结果。

关键优化点:

  • 强制走空间索引:在 PostGIS 中,确保 ST_Within 的第二个参数是索引字段(即 r.geom),不要写成 ST_Within(r.geom, ST_Point(...)),否则索引失效
  • 加地理围栏预过滤:先用 ST_DWithin(ST_Transform(ST_Point(lng, lat), 4326), ST_Transform(r.center_point, 4326), 100000) 快速筛出 100km 内的候选区域,再精确判断
  • 避免 SELECT *:只 SELECT 需要的区域字段(如 r.province_name, r.city_code),别把整个 geom 拉出来
  • 小表驱动大表:把 dim_region 当驱动表(FROM dim_region r),用 LATERAL 关联原始数据,配合 ST_Intersects + 索引,有时比大表驱动快一个数量级

MySQL 5.7 没空间函数怎么办

只能放弃精确多边形匹配,改用「行政中心点 + 距离阈值」近似法,适合对精度要求不高的运营报表。

操作方式:

  • 维度表增加 center_lat、center_lng、radius_km 三列(半径可按地级市平均面积估算)
  • 用 Haversine 公式算球面距离:SELECT *, 6371 * ACOS(LEAST(1.0, COS(RADIANS(lat)) * COS(RADIANS(center_lat)) * COS(RADIANS(lng - center_lng)) + SIN(RADIANS(lat)) * SIN(RADIANS(center_lat)))) AS distance_km FROM raw_data d JOIN dim_region r ON distance_km
  • 缺点明显:圆形覆盖无法处理狭长区域(如甘肃走廊),且无索引,大数据量需加 lat BETWEEN ... AND ... 和 lng BETWEEN ... AND ... 先粗筛

真正难的不是写那几行 SQL,而是确认每一条坐标属于哪个“真实世界里的行政主体”——这背后涉及坐标系、行政区划变更、飞地归属、甚至国界争议。上线前务必抽样人工核验 50 条边界案例。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

4363

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

911

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1149

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

6301

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3123

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

6260

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

8501

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1150

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1012

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.8万人学习