[英]how to optimize query with conditional join?
我需要優化查詢,其中聯接取決於條件
我有兩張桌子
Table1有兩列,可以將它們稱為A和B列,它們可以與table2列C有關,
如果列B為空,則必須將t1.A與t2.C匹配如果列B不為空,則必須將t1.B與t2.C匹配
最后我需要知道t1上的哪些條目在t2上不匹配...
更詳細地說,t1是客戶表,而A和B都是客戶代碼。 A代碼永遠不會與B代碼相同,並且在存在B的情況下,B具有優先權(B是新的客戶代碼,而舊客戶則沒有)。在B為空的情況下,A是代碼使用)(所有這些都是因為B列是新列,而舊客戶端的B值為空)。
t2是購買表。 t2.C是客戶端代碼,但是在這種情況下是單個列,它存儲舊客戶端的A代碼和新客戶端的B代碼。
我唯一想做的就是知道哪個客戶還沒有購買商品,並盡可能高效地進行查詢。
我提出了幾個查詢,但是由於條件的處理方式,它們非常慢,我想:
第一次嘗試:
select *
from t1
left join t2 on (t1.A = t2.C or t1.B = t2.C)
where t2.D is null;
請注意,我可以使用OR條件,因為我知道t1.A永遠不會與任何t1.B相同,因此在t2.C中,它僅與A或B匹配,但絕不會與兩者匹配(假定條件是保證)。 查詢是如此緩慢,以至於在我的sql客戶端中超時。
第二次嘗試
select *
from t1
left join t2 on (if(t1.B is null, t1.A = t2.C, t1.B = t2.C))
where t2.D is null;
在這種情況下,比較條件取決於t1.B,如果為null,則與A進行比較,如果不為B,則與B進行比較。同樣,查詢非常慢。
我想我可以只使用兩個聯接,並為每個聯接使用每個條件(A或B),但是我不知道如何實現它,特別是因為我只需要獲得A o B都沒有的情況t2比賽。 (即,沒有t2購買的t1客戶)
在這種情況下,如何建立更有效的查詢?
謝謝
如果您在t1.A
或t1.B
上沒有索引,那么我懷疑IFNULL將是您最好的選擇:
select *
from t1
left join t2 on ifnull(t1.B, t1.A) = t2.C
where t2.D is null;
但是,如果對任一列都建立了索引,我懷疑您可以通過使用UNION ALL
來獲得最佳性能:
select *
from t1
left join t2 on t1.A = t2.C
where t2.D is null
and t1.B is null
union all
select *
from t1
left join t2 on t1.B = t2.C
where t2.D is null
and t1.B is not null;
原因是在編譯過程中,優化器將不知道是否對連接使用t1.A
或t1.B
,因此無法選擇索引,而是選擇表掃描,但是如果將其分為兩個查詢,它將知道哪個要在聯接上使用的列,並且可以使用適當的索引。
las,執行條件聯接往往會導致非常差的查詢性能。 在這種情況下,您正在測試兩個值,並且大概正在尋找是否都不存在。 嘗試將其分為兩個聯接:
select *
from t1 left join
t2
on t1.A = t2.C left join
t2 t2a
on t1.B = t2a.C
where t2.D is null and t2a.D is null;
這將允許查詢使用A,B和C上的索引。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.