我的结构很简单:
我ways
由多个points
组成。每个point
都有x和y位置。
方法是在额外的表wayspoints
的帮助下定义的,其中包含wid
和pid
列。
我要做的是在给定的x和y的一定距离内获取所有方式(包含所有点)。
我通过检查点x,y和给定的x,y之间的差异来做到这一点。
我遇到的问题是我不想要距离内的所有点,而是所有属于距离内各点都有的点。
在我有这个要求之前,我的查询运行了大约100毫秒,获得了100万点。由于我现在需要各自的方式,我添加了一个子查询,现在需要大约4-5秒来获取。
这对我来说是不可接受的。这是sql(数字是给定的x和y坐标):
SELECT concat(WAYS.id, '|',WAYS.name) "id", POINTS.x, POINTS.y
FROM WAYS, WAYPOINTS, POINTS
WHERE WAYPOINTS.WID = WAYS.ID AND
WAYPOINTS.PID = POINTS.ID AND
WAYPOINTS.WID IN (SELECT w.ID
FROM WAYS w, WAYPOINTS wp, POINTS p
WHERE wp.WID = w.ID AND wp.PID = p.ID
AND p.x < (51.739400 + 0.01)
AND p.x > (51.739400 - 0.01)
AND p.y < (8.710202 + 0.01)
AND p.y > (8.710202 - 0.01);
如果我至少可以达到最大1秒,这将是不错的。我知道我问了很多,因为解决方案已经开始了,但我觉得必须有一些我在这里缺少的东西..
PS:我已经为每个列添加了一个索引。
答案 0 :(得分:1)
SELECT p.*
FROM points AS pWithin
INNER JOIN waypoints AS pwWP ON pWithin.ID = pwWP.PID
INNER JOIN way AS pwW ON pwWP.WID = pwW.ID
INNER JOIN waypoints AS wp ON pwW.ID = wp.WID
INNER JOIN points AS p ON wp.PID = p.ID
WHERE pWithin.x < (51.739400 + 0.01)
AND pWithin.x > (51.739400 - 0.01)
AND pWithin.y < (8.710202 + 0.01)
AND pWithin.y > (8.710202 - 0.01);
WHERE
和points
的第一个引用找到“距离内的点”,接下来的两个连接用于查找这些点的方式,最后两个连接找到点在这些方面。
显然,您可以将p.*
替换为您想要的实际结果数据。
编辑:您可能需要注意的一件事是,如果way
在距离内有多个点,那么它的所有点都将显示多次。只需将SELECT
更改为SELECT DISTINCT
即可轻松解决问题。
答案 1 :(得分:0)
是的,您是否尝试将该子查询创建为CTE?
例如,您可以编写类似
的内容WITH (SELECT w.ID
FROM WAYS w, WAYPOINTS wp, POINTS p
WHERE wp.WID = w.ID AND wp.PID = p.ID
AND p.x < (51.739400 + 0.01)
AND p.x > (51.739400 - 0.01)
AND p.y < (8.710202 + 0.01)
AND p.y > (8.710202 - 0.01) as CTE
SELECT concat(WAYS.id, '|',WAYS.name) "id", POINTS.x, POINTS.y
FROM WAYS, WAYPOINTS, POINTS, cte
WHERE WAYPOINTS.WID = WAYS.ID AND
WAYPOINTS.PID = POINTS.ID AND
WAYPOINTS.WID = cte.id
您需要将查询的效果与CTE查询进行比较;
这样做你就会写
EXPLAIN ANALYZE (
*the entire query*
);
答案 2 :(得分:0)
不正确这就是你要问的。 试试这个。你应该只获得那些点标准为真的Waypoint。
SELECT concat(WAYS.id, '|',WAYS.name) "id", POINTS.x, POINTS.y
FROM WAYS, WAYPOINTS, POINTS
WHERE WAYPOINTS.WID = WAYS.ID AND
WAYPOINTS.PID = POINTS.ID AND
AND Points.x < (51.739400 + 0.01)
AND points.x > (51.739400 - 0.01)
AND points.y < (8.710202 + 0.01)
AND points.y > (8.710202 - 0.01);
答案 3 :(得分:0)
替代方法:使用exists()加入桥接表。这样可以避免最终结果出现重复。
SELECT concat(w.id, '|',w.name) "id", p.x, p.y
FROM WAYS w
JOIN POINTS p ON EXISTS ( -- Join on bridge-table
SELECT *
FROM WAYPOINTS wp
WHERE wp.WID = w.ID
AND wp.PID = p.ID
AND EXISTS ( -- waypoints that contain a particular point
SELECT*
FROM WAYPOINTS wp2
JOIN POINTS p2 ON wp2.PID = p2.ID
WHERE wp2.WID = wp.WID -- same way as outer
AND p2.x < 51.739400 + 0.01
AND p2.x > 51.739400 - 0.01
AND p2.y < 8.710202 + 0.01
AND p2.y > 8.710202 - 0.01
)
);