SQL查询中WHERE NOT过滤逻辑失效,如何筛选完全符合经纬度范围的轨迹?
解决轨迹筛选中经纬度范围的问题
我明白你的问题所在了——你现在的查询逻辑其实是在筛选存在至少一个符合经纬度范围的位置的轨迹,但你真正要的是所有关联位置都完全在经纬度范围内的轨迹,这两者的逻辑差别很大!
原查询的问题拆解
你的INNER JOIN会把每条轨迹和它关联的所有位置一一对应成多行数据,后续的AND NOT条件只是过滤掉那些单个位置超出范围的行,但如果一条轨迹关联了多个位置,只要其中有一个位置符合范围,这条轨迹就会因为那一行匹配成功而被保留(即使其他超出范围的行被过滤了)。DISTINCT只是让结果不重复显示,但本质上这条轨迹是包含超出范围的位置的,这就是为什么你还能看到不符合预期的结果。
正确的解决方案
下面提供两种可靠的实现方式,都能确保筛选出所有关联位置都完全在限定经纬度范围内的轨迹:
方案1:使用NOT EXISTS子查询(推荐)
通过子查询检查当前轨迹对应的车辆是否存在任何超出范围的位置,如果不存在,则保留该轨迹:
SELECT DISTINCT mobtrack.track.id AS track_id, mobtrack.track.user_id AS vehicle_id FROM mobtrack.track WHERE mobtrack.track.user_id = 1343904522 AND mobtrack.track.distance BETWEEN 20 AND 25 AND NOT EXISTS ( SELECT 1 FROM sensor.location WHERE sensor.location.vehicle_id = mobtrack.track.user_id AND ( sensor.location.longitude < 11.50 OR sensor.location.longitude > 11.72 OR sensor.location.latitude < 48.14 OR sensor.location.latitude > 48.34 ) ) LIMIT 100;
方案2:使用GROUP BY + HAVING聚合校验
将同一轨迹的所有关联位置分组,通过MIN和MAX判断组内所有位置的经纬度是否都在限定范围内:
SELECT mobtrack.track.id AS track_id, mobtrack.track.user_id AS vehicle_id FROM mobtrack.track INNER JOIN sensor.location ON mobtrack.track.user_id = sensor.location.vehicle_id WHERE mobtrack.track.user_id = 1343904522 AND mobtrack.track.distance BETWEEN 20 AND 25 GROUP BY mobtrack.track.id, mobtrack.track.user_id HAVING MIN(sensor.location.longitude) >= 11.50 AND MAX(sensor.location.longitude) <= 11.72 AND MIN(sensor.location.latitude) >= 48.14 AND MAX(sensor.location.latitude) <= 48.34 LIMIT 100;
补充说明
你提到的正向筛选(直接保留经纬度在范围内的轨迹)之所以不行,是因为它只是选出了那些位置符合范围的行,但如果一条轨迹同时存在符合和超出范围的位置,只要有一个符合的行,这条轨迹就会被包含进来。而你需要的是完全没有超出范围位置的轨迹,所以必须校验该轨迹关联的所有位置。
内容的提问来源于stack exchange,提问作者User5644
相关产品推荐
相关产品推荐

