-4

我有这张桌子:

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 的索引

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

4

1 回答 1

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

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

希望这可以帮助

于 2013-08-04T17:45:54.877 回答