子查询结果作为函数参数

问题描述 投票:0回答:1

我有两张桌子:

  • 实体: | id 无符号整数 | pos 点| ... |
  • 关系: | id 无符号整数 | srcId 无符号整数 | dstId 无符号整数 | ... |
两个表中的

id 都是主键。

Relation 的

srcIddstId 是对 Entities id 列的引用(外键)。

我正在尝试创建一个程序来选择以下任一关系为真的所有关系:

  1. srcId 实体位于 newRect 内部和 oldRect 外部 AND dstId 实体位于 newRect 内部且 oldRect 外部
  2. srcId 实体位于 newRect 内部和 oldRect 外部 AND dstId 实体位于 newRect 之外且位于 oldRect 之外
  3. srcId 实体位于 newRect 之外且位于 oldRect 之外并且 dstId 实体位于 newRect 内部且 oldRect 外部
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
mysql stored-procedures subquery
1个回答
1
投票

正如 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)
    )
© www.soinside.com 2019 - 2024. All rights reserved.