2013-07-15 23 views
0

我讀過SELECT ... WHERE SELECT ...很慢,我應該使用連接。如何用連接來替換`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:

  • 編號:INTEGER PRIMARY KEY
  • 數據1:XML
  • 數據2:INTEGER

表2:

  • 編號:INTEGER

表3:

  • 編號:INTEGER PRIMARY KEY
+0

PDO不會幫你。 –

+0

首先看一下EXPLAIN,看看是否存在優化器無法解決的問題 - 然後您可以擔心調優 - 而不是試圖遵循全局規則。 – Randy

+0

@Randy我從來沒有理解如何使用EXPLAIN。如果我在查詢前寫入EXPLAIN並在phpliteadmin上運行它,它只會顯示「* 0行受影響*」 – Oriol

回答

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上有一個索引)。

+0

謝謝!但是在Table2上創建索引後,'Id not in(從表2中選擇Id)'不使用它,但'not exists(從Table2選擇1,其中Table2.Id = Table1.Id)'',看起來它與連接相比,花費的時間相同 – Oriol

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; 
+0

當我運行你的代碼時,我從「:syntax error *」得到「* ERROR:near」「 – Oriol