admin

计数查询花费的时间太长-已超过24小时

sql

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

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
...

但是花费的时间太长,一天之后查询仍在运行…是否有提高性能的方法?我大约有四百万行

谢谢


阅读 166

收藏
2021-07-01

共1个答案

admin

您的查询相当复杂。我觉得你只是想计算的组合iditem。如果是这样,这是一个简单的聚合:

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 join作为“驱动程序”,因为它定义了输出行。

2021-07-01