能否在MariaDB中结合窗口函数与空间函数使用?
问题描述
我尝试计算追踪器的总移动距离,但在尝试结合窗口函数与空间函数时遇到了奇怪的错误。
单独执行以下查询是有效的:
select t.createdAt, ST_AsText(lead(t.location) over (ORDER BY t.createdAt desc)), st_astext(t.location) from track t order by t.createdAt desc limit 1,1;
以下查询也可正常执行:
select t.createdAt, st_astext(t.location), st_distance_sphere(t.location, t.location) from track t order by t.createdAt desc limit 1,1;
但同时使用两者时会报错:
select t.createdAt, ST_AsText(lead(t.location) over (ORDER BY t.createdAt desc)), st_astext(t.location), st_distance_sphere(t.location, t.location) from track t order by t.createdAt desc limit 1,1;
错误信息:
Out of range error: Longitude should be [-180,180] in function ST_Distance_Sphere
疑问:是否可以结合窗口函数与空间函数使用?这是MariaDB的限制还是我的查询写法有误?
补充:删除一条旧的无效位置记录后,所有查询都能正常运行,但我不理解为何无效记录会引发错误,原以为上述查询只会访问最新的记录。
解答
- 窗口函数与空间函数完全可以结合使用,这不是MariaDB的限制,你的查询写法本身没有语法问题。
- 无效旧记录引发错误的核心原因:
窗口函数(如lead())的执行逻辑是先对全表数据进行计算,之后才会应用limit限制返回结果。也就是说,哪怕你最后只取1条数据,lead()在执行时会遍历整个track表的所有记录,包括那条无效的旧位置。
当查询中加入ST_Distance_Sphere后,MariaDB会对所有被扫描到的location字段进行经纬度合法性校验(因为该函数要求经度在[-180,180]、纬度在[-90,90]范围内)。那条旧记录的经纬度不符合规范,就触发了错误。
而单独执行前两个查询时,要么没有调用ST_Distance_Sphere(第一个查询),要么limit让MariaDB提前终止了全表扫描,只读取了最新的有效记录,没触碰到无效数据,所以没有报错。 - 优化建议:
- 定期清理无效的空间数据,确保所有
location字段的经纬度符合规范。 - 如果暂时不能清理数据,可以在子查询中先过滤掉无效记录:
select t.createdAt, ST_AsText(lead(t.location) over (ORDER BY t.createdAt desc)), st_astext(t.location), st_distance_sphere(t.location, t.location) from ( select * from track where ST_X(location) between -180 and 180 and ST_Y(location) between -90 and 90 ) t order by t.createdAt desc limit 1,1;
- 定期清理无效的空间数据,确保所有
内容的提问来源于stack exchange,提问作者hurelhuyag
相关产品推荐
相关产品推荐

