如何用连接替换`SELECT ... WHERE SELECT ...`?

时间:2013-07-15 16:01:18

标签: sql sqlite select join

我已经读过SELECT ... WHERE SELECT ...很慢,我应该使用连接。

但我不知道如何替换此代码

SELECT Id
FROM Table1
Where
    (
        Data1 IS NULL
        OR
        (
            Data2=1
            AND
            (SELECT 1 FROM Table2 WHERE Table2.Id=Table1.Id) IS NULL
        )
    )
    AND
    (SELECT 1 FROM Table3 WHERE Table3.Id=Table1.Id) IS NULL

加入。

表格具有以下结构:

表1:

  • Id:INTEGER PRIMARY KEY
  • Data1:XML
  • Data2:INTEGER

表2:

  • Id:INTEGER

表3:

  • Id:INTEGER PRIMARY KEY

2 个答案:

答案 0 :(得分:1)

select Id from Table1 where
  Id not in (select Id from Table3) and
  (Data1 is null or 
   (Data2 = 1 and Id not in (select Id from Table2)));

或者,如果你真的想要加入:

select Id from Table1 left join Table2 on (Table1.Id = Table2.Id)
  left join Table3 on (Table1.Id = Table3.Id)
where Table3.Id is null and
  (Data1 is null or
   (Data2 = 1 and Table2.Id is null));

我预计这两者之间的性能差别不大。查询可能会受益于Table2.Id上的索引(由于它是主键,你在Table3.Id上有一个)。

答案 1 :(得分:0)

将子查询从in移动到from子句有两个关键部分。第一种是使用left outer join,因此第一个表中的行不会无意中丢失。第二种方法是为每个子查询使用select distinct,以避免不必要的重复。

应用于您的查询,结果是:

SELECT t1.Id
FROM Table1 t1 left outer join
     (select distinct id
      from Table2
     ) t2
     on t1.id = t2.id left outer join
     (select distinct id
      from Table3
     ) t3
     on t1.id = t3.id
Where(t1.Data1 IS NULL OR
      (t1.Data2=1 and t2.id is null)
     ) and
     t3.id is null;