SQL选择行并排除子项

时间:2010-11-12 12:19:01

标签: sql mysql

我有两张桌子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

5 个答案:

答案 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的链接),以及然后删除不符合条件的链接 - 留下特定AB中的所有其他链接,这不是您想要的。

但是,我认为内部选择是必要的 但也许可以试试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