我有这张桌子:
ID ITEM
-----------------
0001 345
0001 345
0001 120
0002 567
0002 034
0002 567
0003 567
0004 533
0004 008
......
并且为了得到这个结果:
ID ITEM CNT
1 008 0
1 034 0
1 120 1
1 345 2
1 533 0
1 567 0
2 008 0
2 034 1
...
CNT是每个不同ID的每个项目的出现
我运行此查询:
select driver.id, driver.item, coalesce(count(t1.id), 0)
from (select id.id, item.item
from (select distinct id from Table1) id cross join
(select distinct item from Table1) item
) driver left outer join
Table1 t1
on driver.id = t1.id and driver.item = t1.item
group by driver.id, driver.item;
此查询需要一段时间,但一天后仍未完成。 这是EXPLAIN的结果:
idx_id和idx_code是ID和ITEM的索引
您能否给我一些关于如何改进查询的提示,以便它可以更快地运行并希望完成?感谢
答案 0 :(得分:3)
我的建议是:分而治之。为中间步骤创建临时表,索引它们,然后使用它们来获得最终结果。
具体做法是:
-- The deduplicated item list
drop table if exists temp_items;
create temporary table temp_items
select distinct item from Table1;
alter table temp_items
add primary key (item);
-- The deduplicated id list
drop table if exists temp_ids;
create temporary table temp_ids
select distinct id from Table1;
alter table temp_ids
add primary key (id);
-- The cross join
drop table if exist temp_ids_items
create temporary table temp_ids_items
select id, item
from temp_ids, temp_items;
-- Important: Index the cross join
alter table temp_ids_items
add index idx_id(id),
add index idx_item(item); -- Optionally: add unique index idx_dedup(id, item)
现在您可以使用此临时表来获取所需内容:
select
a.id, a.item, coalesce(count(t1.id), 0)
from
temp_ids_items as a
left join Table1 as t1 on (a.id = t1.id and a.item=t1.item)
group by
a.id, a.item;
我认为您不需要coalesce()
函数(如果计算null
值,结果为零),但这只是一个意见。
请记住:临时表仅对创建它们的连接可见,并且在关闭连接时它们将被删除。我认为将所有上述过程放在存储过程中可能很有用。
希望这有帮助