我有2个表:呼叫(10,000行),客户关系管理(2,500万行)我想做呼叫左加入CRM。
select *
from calls a
left join crm b
on (
(a.customerID = b.customerID)
OR
(a.Number1 in (b.Number_A,b.Number_B))
OR
(a.Number2 in (b.Number_A,b.Number_B))
);当我只执行customerID连接时,它运行得很好。但上面的代码会导致超时并导致崩溃。
发布于 2021-09-06 17:19:34
我建议使用多个left join:
select c.*,
coalesce(cc.col1, c1a.col1, c1b.col1, c2a.col1, c2b.col1)
from calls c left join
crm cc
on c.customerID = cc.customerID left join
crm c1a
on c.Number1 = c1a.Number_A left join
crm c1b
on c.Number1 = c1b.Number_B left join
crm c2a
on c.Number2 = c2a.Number_A left join
crm c2b
on c.Number2 = c2b.Number_B;这样就可以利用crm(CustomerId)、crm(Number1)和crm(Number2)上的索引。
发布于 2021-09-06 20:05:41
有时,当用两个用UNION粘合在一起的查询替换一个包含两个条件的OR查询时,这会产生一个更好的执行计划。我从来不明白为什么DBMS优化器自己不考虑这一点。我不知道这对PostgreSQL是不是真的。但这可能值得一试。
在您的例子中,查询中有一个外连接。这让事情变得复杂起来。使用单独的查询,我们可以同时获得呼叫的外部联接和匹配crm行,在这种情况下必须消除前者。
select *
from
(
select * from calls left join crm on crm.customerID = calls.customerID
union
select * from calls left join crm on crm.number_a = calls.number1
union
select * from calls left join crm on crm.number_a = calls.number2
union
select * from calls left join crm on crm.number_b = calls.number1
union
select * from calls left join crm on crm.number_b = calls.number2
) data
order by rank() over (partition by calls.id order by case when crm.id is null then 2 else 1 end)
fetch first row with ties;为了更快地工作,查询中的每列应该有一个索引,即6个单列索引。
这是否比原始查询更快取决于很多因素。主要:匹配越少越好。
https://stackoverflow.com/questions/69077843
复制相似问题