我有一个MySQL查询,根据用户的位置和区域边界将用户映射到区域:
UPDATE User u SET u.zoneId = (
SELECT z.id FROM Zone z
WHERE ST_Contains(z.boundary, u.location)
ORDER BY z.level DESC
LIMIT 1
);
这样可以正常工作,但由于它为每条记录执行子查询,所以速度很慢。
是否可以使用JOIN重写它,即使它在子查询中使用ORDER BY ... LIMIT 1
?
这个ORDER BY ... LIMIT 1
是必需的,因为几个封装区域可以匹配一个位置,并且只能分配最小的一个(最高级别)。
答案 0 :(得分:0)
在没有任何测试数据或完整DDL的情况下,我无法对此进行测试,但这可能会有效。使用连接和子查询,但是将子查询隐藏在额外的级别,这可能允许MySQL忽略他在子查询中使用要更新的表。
依赖于具有唯一键的用户表(我刚把它称为id)。
UPDATE User u
INNER JOIN Zone z
ON ST_Contains(z.boundary, u.location)
INNER JOIN
(
SELECT id, MaxLevel
FROM
(
SELECT u.id, MAX(z.level) AS MaxLevel
FROM User u
INNER JOIN Zone z
ON ST_Contains(z.boundary, u.location)
GROUP BY u.id
) Sub1
) Sub2
ON u.id = Sub2.id AND z.level = Sub2.MaxLevel
SET u.zoneId = z.id
如果你可以在SQL小提琴中设置一些测试数据,我可以测试一下。