2

好的,很可能我做错了什么,但是按照这里用户的建议,我运行了这个查询:

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 万行

谢谢

4

3 回答 3

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 行用于不同的行(我不认为 MySQL 对此进行了更好的优化)。首先做不同的(至于驱动程序)大大减少了数据量。

编辑:

有一类 SQL 问题,您需要查看两个或多个项目的所有组合,然后确定每个人的值(即使是那些不存在于数据中的值)或找到那些不存在于数据的值。这些问题带来了同样的问题:你如何获得关于不在数据中的值的信息?

我提倡的解决方案是创建一个包含所有可能组合的表,然后left [outer] join用于剩余的表。我将此称为“驱动程序”表,因为此查询中的行通过定义后续连接的总体来“驱动”查询。

该术语与评论中的参考相当一致。该注释从优化器的角度使用该术语。一些连接算法——尤其是嵌套循环和索引查找——以不同的方式处理连接的两侧;对于这些,一侧是“驾驶/司机”表。例如,当从一个大表连接到一个小引用表时,大表是驱动表,另一个表是通过索引访问的。其他连接算法——例如合并连接和散列连接(通常)——将双方视为相同,因此该概念不太适用。

从逻辑的角度来看,我用它来表示定义人口的查询。一个重要的相似之处在于,对于左/右外连接,两个定义实际上是相同的。优化器通常会选择 a 中的第一个表left join作为“驱动程序”,因为它定义了输出行。

于 2013-08-01T14:25:10.943 回答
1

如果您想要实现的唯一目标是按idand分组的计数item,您为什么不这样做:

SELECT ID, Item, COUNT(1)
FROM Table 1
GROUP BY ID, Item

就这么简单!

于 2013-08-01T14:26:30.533 回答
-2

您查询的速度问题可能是“不同的”,它在功能上选择所有数据,排序,然后在返回结果之前消除重复项。“Distinct”是一项昂贵的功能。

于 2013-08-01T14:27:40.013 回答