我有两张桌子A和B. A是B的父母。 我试图找到所有没有特定B作为孩子的所有。 通常我会做
SELECT A.id FROM A WHERE A.id NOT IN (SELECT B.AId FROM B WHERE B.someFK = foo);
但是出于性能原因,我不想使用内部选择。 我尝试过类似的东西:
SELECT A.id FROM A LEFT JOIN B ON (A.id = B.AId) WHERE B.someFK != foo OR B.someFK IS NULL
问题是这个返回因为它有多个孩子而不管他们是否有指定的B.
编辑: 将B.id更改为B.someFK
答案 0 :(得分:1)
我会使用exists子句,因为它是出于这样的目的而制作的:
SELECT A.id FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.id = foo and B.AId=a.id);
在大多数数据库中,它比大型记录集的in
子句(基本上是一个要比较的数组)更高效。
聚合也很昂贵,所以使用exists
语句是imho的方法。不过,您可以尝试为您的方案进行聚合。
答案 1 :(得分:1)
您的LEFT JOIN
将为每个A
- B
链接返回一行(或A
的一行,但没有指向B
的链接),以及然后删除不符合条件的链接 - 留下特定A
在B
中的所有其他链接,这不是您想要的。
但是,我认为内部选择是必要的
但也许可以试试EXISTS
:
SELECT A.id
FROM A
WHERE NOT EXISTS (SELECT * FROM B WHERE B.AId = A.id AND B.someFK = foo);
答案 2 :(得分:0)
尝试在父表上使用MAX约束。我有一段时间没有使用MySql,但这应该给你一个想法
SELECT A.id, MAX(B.AId) FROM A
LEFT JOIN B ON (A.id = B.AId)
WHERE B.id != foo OR B.id IS NULL
GROUP BY A.id
答案 3 :(得分:0)
试试这个
SELECT DISTINCT A.id FROM A
LEFT JOIN B ON (A.id = B.AId)
WHERE B.id != foo OR B.id IS NULL
答案 4 :(得分:0)
您应该将整个条件放在LEFT JOIN中。
就重复行而言,只需DISTINCT即可。
SELECT DISTINCT A.id
FROM A
LEFT JOIN B
ON A.id = B.AId AND B.someFK = "foo"
WHERE B.AId IS NULL