Sql-Server

子查詢中 where 語句的效果(去除不必要的連接)

  • January 12, 2016

請考慮以下查詢:

select * 
from parent p
where p.id in (
 select p.id
 from parent p
 inner join child c on c.parentId = p.id
 where p.age > 50
)

為了保存連接,將查詢重寫為此是否安全(通常!)?子查詢包含與外部查詢相同的別名(不是拼寫錯誤)。

select * 
from parent p
where p.id in (
 select p.id
 from child c 
 where c.parentId = p.id 
 and p.age > 50
)

我擔心子查詢的 where 語句將應用於外部查詢的結果。這個推理正確嗎?

請注意,上面的查詢只是一個簡單的範例,真正的查詢很大,其中子選擇位於某個或條件中的某個位置並包含多個連接。

也許借助一些重寫更容易看到。您的第一個查詢可以重寫(在不同級別使用相同的別名使其有點難以理解):

select * 
from parent p1
where exists (
 select 1  
 from parent p2
 join child c on c.parentId = p2.id
 where p2.age > 50
   and p1.id = p2.id 
)

假設 id 在 parent 中是唯一的,這可以重寫為:

select * 
from parent p1
where exists (
 select 1  
 from child c 
 where c.parentId = p1.id
   and p1.age > 50
)

反過來可以將其重寫為您的查詢。

因此,您可以消除子選擇中針對父級的聯接。但是,您的第二個查詢在編寫時有點難以理解。我會建議(我猜你的意圖)

select * 
from parent p1
where exists (
 select 1  
 from child c 
 where c.parentId = p1.id
)
and p1.age > 50

如果 parent.id 不是唯一的,則上述內容不成立

為什麼要保存加入?

這是有效的

,這假設在父級中不重複

select distinct p.* 
 from parent p
 join child c 
       on c.parentId = p.id 
      and p.age > 50

沒有加入

select p.* 
 from parent p
where exists (select 1 from child c 
               where c.parentId = p.id)
  and p.age > 50 

select p.* 
 from parent p
where exists (select 1 from child c 
               where c.parentId = p.id
                 and p.age > 50)

至於您查詢中的別名,最好的選擇是避免重複別名,

否則只需測試

引用自:https://dba.stackexchange.com/questions/125990