好的,我可能做错了什么,但是按照用户的建议,我运行这个查询:
SELECT id, item,
(SELECT COUNT(item) FROM Table1 WHERE id=a.id AND item=a.item) cnt
FROM (SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a
ORDER BY id, item;
在这张桌子上:
ID ITEM
-----------------
0001 345
0001 345
0001 120
0002 567
0002 034
0002 567
0003 567
0004 533
0004 008
...
为了得到这个结果:
ID ITEM CNT
1 8 0
1 34 0
1 120 1
1 345 2
1 533 0
1 567 0
2 8 0
2 34 1
...
但它花了太长时间,查询仍然在一天后运行... 有没有办法提高性能?我有大约400万行
谢谢
答案 0 :(得分:6)
您的查询非常复杂。我想你只想计算id
和item
的组合。如果是这样,这是一个简单的聚合:
select id, item, count(*)
from Table1 a
group by id, item;
如果您想要显示所有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;
原始查询有以下声明:
(SELECT DISTINCT a.id,b.item FROM Table1 a, Table1 b) a
这是完整的笛卡尔产品,然后做一个独特的。因此,如果您的表有100,000行,那么中间表有10,000,000,000行用于distinct(我不认为MySQL会更好地优化这一行)。首先执行不同的操作(对于驱动程序)会大大减少数据量。
编辑:
有一类SQL问题,您需要查看两个或更多项的所有组合,然后确定每个人的值(即使数据中不存在的值)或找到不是的值在数据中。这些问题带来了同样的问题:如何获得有关数据中没有数据的信息?
我提倡的解决方案是创建一个包含所有可能组合的表,然后对剩余的表使用left [outer] join
。我称之为“驱动程序”表,因为此查询中的行通过定义后续连接的填充来“驱动”查询。
该术语与评论中的参考文献相当一致。评论使用优化程序角度的术语。一些连接算法 - 特别是嵌套循环和索引查找 - 以不同方式处理连接的两边;对于这些,一方是“驾驶/司机”表。例如,当从大表连接到小型参考表时,大表是驱动表,而另一个表是通过索引访问的。其他连接算法 - 例如合并连接和散列连接(通常) - 对待双方都是相同的,因此这个概念在那里不太适用。
从逻辑角度来看,我用它来表示定义总体的查询。一个重要的相似之处在于,对于左/右外连接,两种定义在实践中是相同的。优化器通常会选择left join
中的第一个表作为“驱动程序”,因为它定义了输出行。
答案 1 :(得分:1)
如果您想要实现的唯一目标是按id
和item
分组的计数,为什么不呢:
SELECT ID, Item, COUNT(1)
FROM Table 1
GROUP BY ID, Item
就这么简单!
答案 2 :(得分:-2)
查询中的速度问题可能是“不同的”,它在功能上选择所有数据,排序,然后在返回结果之前消除重复项。 “Distinct”是一项昂贵的功能。