Sql-Server
子查詢中 where 語句的效果(去除不必要的連接)
請考慮以下查詢:
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)
至於您查詢中的別名,最好的選擇是避免重複別名,
否則只需測試