我需要一些帮助来在MySQL中重写我的查询

时间:2013-08-04 16:58:23

标签: mysql database

我有这张桌子:

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的结果:

Explain

idx_id和idx_code是ID和ITEM的索引

您能否给我一些关于如何改进查询的提示,以便它可以更快地运行并希望完成?感谢

1 个答案:

答案 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值,结果为零),但这只是一个意见。

请记住:临时表仅对创建它们的连接可见,并且在关闭连接时它们将被删除。我认为将所有上述过程放在存储过程中可能很有用。

希望这有帮助