sql - 多层相关子查询

时间:2013-04-18 01:49:07

标签: sql sql-server correlated-subquery

我有table A, B and C

我想返回表A中表B中不存在的所有条目,并且表C中不存在该列表中的所有条目。

select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)

这给了我A中不在B中的条目的第一个结果。但是现在我只想要这个结果中那些也不在C中的条目。

我尝试了以下的口味:

select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)

但这不是正确的逻辑。如果有办法存储第一个查询的结果,然后从表C中不存在的结果中选择*但是我不知道该怎么做。我很感激帮助。

5 个答案:

答案 0 :(得分:3)

试试这个:

select * from (
  select a.*, b.id as b_id, c.id as c_id 
  from table_A as a
  left outer join table_B as b on a.id = b.id
  left outer join table_C as c on c.id = a.id
) T
where b_id is null
  and c_id is null

另一个实现是:

select a1.*
from table_A as a1
inner join (
  select a.id from table_A
  except  
  select b.id from table_B
  except
  select c.id from table_c
) as a2 on a1.id = a2.id

请注意here所述的子查询形式的限制。第二个实现,通过最简洁和清晰地描述SQL Server的所需操作,可能是最有效的。

答案 1 :(得分:2)

如何使用LEFT JOIN

SELECT  a.*
FROM    TableA a
        LEFT JOIN TableB b
            ON a.ID = b.ID
        LEFT JOIN TableC c
            ON a.ID = c.ID
WHERE   b.ID IS NULL AND
        c.ID IS NULL

答案 2 :(得分:2)

您的第二个查询(外部部分)中有两个WHERE子句。这不是有效的SQL。如果你删除它,它应该按预期工作:

select * from table_A as a
where not exists (select 1 from table_B as b
                  where a.id = b.id)
AND
      not exists (select 1 from table_C as c            -- WHERE removed
                  where a.id = c.id) ;

SQL-Fiddle (thnx @Alexander)中进行测试

答案 3 :(得分:2)

使用NOT EXISTS运算符的另一个选项

SELECT *
FROM dbo.test71 a 
WHERE NOT EXISTS(
                 SELECT 1
                 FROM (SELECT b.ID
                       FROM dbo.test72 b
                       UNION ALL
                       SELECT c.ID
                       FROM dbo.test73 c) x
                 WHERE a.ID = x.ID
                 )  

SQLFiddle上的演示

来自@ ypercube.Thank的选项目前;)

SELECT *
FROM dbo.test71 a 
WHERE NOT EXISTS(
                 SELECT 1
                 FROM dbo.test72 b
                 WHERE a.ID = b.ID  
                 UNION ALL
                 SELECT 1
                 FROM dbo.test73 c
                 WHERE a.ID = c.ID
                 );

SQLFiddle上的演示

答案 4 :(得分:1)

我不喜欢“不存在”,但如果出于某种原因,你似乎更合乎逻辑;然后你可以为你的第一个查询使用别名。随后,您可以重新应用另一个“不存在”子句。类似的东西:

SELECT * FROM 
  ( select * from tableA as a
  where not exists (select 1 from tableB as b
  where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
  SELECT 1 FROM tableC as c
  WHERE c.id = A_NOT_IN_B.id
)