我正在尝试从表A中选择项目,其中表B中的等价项目存在给定约束。表A中每个id有一行,但每个表A行有很多行。
select distinct A.id
from A inner join B on B.a_id = A.id
where B.x >= 5 and B.x <= 10;
我想知道是否有一个SQL连接子句可用于确保每个表A行只能获得一行。
据我了解,查询将找到约束,执行内连接,然后对此执行不同。如果这是正确的,并且有一种更好的方法来指示数据库只从A中获取不同的行,我想知道。我确信有很多方法可以在查询语义的约束下解释和执行查询。我不能声称理解explain
输出。
有没有办法简化这个?如果这有任何区别,我会受限于SQLite。
修改
约束子句有两个约束,在我现在添加的查询时定义。我尽量保持这个问题尽可能简单,但为了回应评论而添加了额外的完整性条款。
答案 0 :(得分:3)
以下是编写查询的另一种方法:
select A.id
from A
where A.id in (select B.a_id from B where B.x > 5)
我认为表现不会更好,但它确实消除了外在的“不同”。
我还会在MySQL中使用另一个版本:
select A.id
from A
where exists (select 1 from B where b.x > 5 and b.a_id = a.id limit 1)
这可能更有效,因为查询可以使用索引查找并在第一次匹配时停止。如果(a_id,x)的B上有索引,则尤其如此。
答案 1 :(得分:1)
如果两个表之间存在(正确执行)FOREIGN KEY
,则通过删除表A
可以获得(轻微)效率增益:
SELECT DISTINCT a_id AS id
FROM B
WHERE x >= 5 and x <= 10 ;
(a_id, x)
上的索引似乎合适,但效率取决于各种参数(ids的百分比与条件x>5
匹配?有多少行具有相同的ID?等等。)
我也会尝试这个查询(在添加上面的索引之后):
SELECT a_id AS id
FROM B
GROUP BY a_id
HAVING MAX(x) >= 5
AND MIN(x) <= 10 ;
当您需要来自A
的数据时,这将有效:
SELECT A.*
FROM A
JOIN
( SELECT a_id
FROM B
GROUP BY a_id
HAVING MAX(x) >= 5
AND MIN(x) <= 10
) AS b
ON b.a_id = a.id ;