代码之家  ›  专栏  ›  技术社区  ›  Jim

SQL选择行并排除子级

  •  5
  • Jim  · 技术社区  · 14 年前

    我有两张桌子A和B。A是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.id改成B.someFK

    5 回复  |  直到 14 年前
        1
  •  1
  •   Falcon    14 年前

    我要遵守存在条款,因为它是为了这样的目的而制定的:

    SELECT A.id FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.id = foo and B.AId=a.id);
    

    在大多数数据库中,它比 in 大型记录集的子句(基本上是要比较的数组)。

    exists 陈述才是我前进的方向。不过,您可以尝试对场景进行聚合。

        2
  •  1
  •   DMA57361    14 年前

    LEFT JOIN 将为每个返回一行 A - B 一个 ),然后删除与条件不匹配的链接-将 ,这不是你想要的。

    不过,我认为内部选择是必要的。
    EXISTS 相反:

    SELECT A.id
    FROM A 
    WHERE NOT EXISTS (SELECT * FROM B WHERE B.AId = A.id AND B.someFK = foo);
    
        3
  •  0
  •   amarsuperstar    14 年前

    尝试对父表使用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
    
        4
  •  0
  •   Null Pointer    14 年前

    试试这个

    SELECT DISTINCT A.id FROM A 
    LEFT JOIN B ON (A.id = B.AId)
    WHERE B.id != foo OR B.id IS NULL
    
        5
  •  0
  •   Gidon Wise    9 年前

    您应该将整个条件放在左连接中。

    对于重复的行,只需区分它。

    SELECT DISTINCT A.id 
    FROM A 
    LEFT JOIN B 
    ON A.id = B.AId AND B.someFK = "foo"
    WHERE B.AId IS NULL