我有两张桌子:
列 id 都是主键。
Relation 的列 srcId 和 dstId 是对 Entities id 列的引用(外键)。
我正在尝试创建一个程序来选择以下任一关系为真的所有关系:
DECLARE oldRect DEFAULT ENVELOPE(LINESTRING(POINT(0, 0), POINT(500, 500)));
DECLARE newRect DEFAULT ENVELOPE(LINESTRING(POINT(0, 0), POINT(1000, 1000)));
SELECT DISTINCT r.*
FROM Entities AS e
JOIN Relations AS r ON e.id IN (r.srcId, r.dstId)
WHERE
ST_CONTAINS(newRect,
SELECT re.pos
FROM Entities AS re
WHERE re.id = srcId
)
AND NOT
ST_CONTAINS(oldRect,
SELECT re.pos
FROM Entities AS re
WHERE re.id = srcId
)
AND
ST_CONTAINS(newRect,
SELECT re.pos
FROM Entities AS re
WHERE re.id = dstId
)
AND NOT
ST_CONTAINS(oldRect,
SELECT re.pos
FROM Entities AS re
WHERE re.id = dstId
)
.... ?;
编辑:我找到了一种方法,想知道是否有更好的方法。如果我创建一个新函数并调用该函数。
CREATE FUNCTION getPos(id INT UNSIGNED) RETURNS POINT
BEGIN
DECLARE pos POINT DEFAULT NULL;
SELECT re.pos INTO pos
FROM Entities AS re
WHERE re.id = id;
RETURN pos;
END
正如 Bill 所说,子查询必须始终用括号括起来。
但是,当您似乎根本不使用
select...from Entities e...join Relations
时,执行 e
就没有意义。你应该select...from Relations
。如果您连接实体两次(一次用于 src,一次用于 dst),则根本不需要子查询。那么就不需要 DISTINCT,因为每个关系行只有一个可能的行。
你的逻辑似乎可以归结为:
dstId Entity is outside of oldRect
AND
srcId Entity is outside of oldRect
AND
(
srcId Entity is inside of newRect
OR
dstId Entity is inside of newRect
)
所以:
select r.*
from Relations r
join Entities se on se.id=r.srcId
join Entities de on de.id=r.dstId
where
not st_contains(oldRect, de.pos)
and not st_contains(oldRect, se.pos)
and (
st_contains(newRect, se.pos)
or st_contains(newRect, de.pos)
)