我需要优化查询,其中联接取决于条件
我有两张桌子
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
用于联接,因此无法选择索引,而是选择进行表扫描,但是如果将其分成两个查询,它将知道在联接上使用哪一列,并可以使用适当的索引。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句