好的,很可能是我做错了什么,但是按照这里用户的建议,我运行以下查询:
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 ...
但是花费的时间太长,一天之后查询仍在运行…是否有提高性能的方法?我大约有四百万行
谢谢
您的查询相当复杂。我觉得你只是想计算的组合id和item。如果是这样,这是一个简单的聚合:
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行用于不同的数据(我认为MySQL对此没有更好的优化)。首先进行区分(对于驱动程序而言)可大大减少数据量。
编辑:
还有一类SQL的问题,你需要看的两个或更多项的所有组合,然后确定每个人的值(即使是那些没有在数据中存在),或者找到那些 没有 在数据中。这些问题也带来了同样的问题:如何获取有关数据中未包含的值的信息?
我主张的解决方案是创建一个具有所有可能组合的表,然后将其left [outer] join用于其余表。我将其称为“驱动程序”表,因为此查询中的行通过定义后续联接的填充来“驱动”查询。
left [outer] join
该术语与注释中的参考完全一致。从优化程序的角度来看,此评论使用的是术语。一些连接算法(特别是嵌套循环和索引查找)对连接的两侧有不同的对待。对于这些,一侧是“驾驶/驱动程序”表。例如,当从大表连接到小参考表时,大表是驱动表,而另一个表则通过索引进行访问。其他联接算法(例如,合并联接和哈希联接(通常))对双方相同,因此该概念在此处不太适用。
从逻辑角度来看,我使用它来表示定义总体的查询。一个重要的相似之处是,对于左/右外部联接,实际上两个定义都是相同的。优化器通常会选择中的第一个表left join作为“驱动程序”,因为它定义了输出行。
left join