在MySQL

时间:2017-03-08 04:04:33

标签: mysql performance group-by grouping counting

我有一些数据(约70,000行),其格式与下面类似。

+-----------+-----+-----+----+-----------+
|    ID     |  A  |  B  | C  | Whatever  |
+-----------+-----+-----+----+-----------+
| 1banana   |  42 |   0 |  2 | Um        |
| fhqwhgads | 514 |   6 |  9 | Nevermind |
| 2banana   |  69 |  42 |  0 | NULL      |
| pears     |  18 |  96 |  2 | 8.8       |
| zubat2    |  96 |   2 | 14 | "NULL"    |
+-----------+-----+-----+----+-----------+

我想创建一个输出表来计算每个数字在三列中的任何一列中出现的次数,例如:

+--------+---------+---------+---------+-----+
| Number | A count | B count | C count | sum |
+--------+---------+---------+---------+-----+
|      0 |       0 |       1 |       1 |   2 |
|      2 |       0 |       1 |       2 |   3 |
|      6 |       0 |       1 |       0 |   1 |
|      9 |       0 |       0 |       1 |   1 |
|     14 |       0 |       0 |       1 |   1 |
|     18 |       1 |       0 |       0 |   1 |
|     42 |       1 |       1 |       0 |   2 |
|     69 |       1 |       0 |       0 |   1 |
|     96 |       1 |       1 |       0 |   2 |
|    514 |       1 |       0 |       0 |   1 |
+--------+---------+---------+---------+-----+

(在我的实际使用中,输入表中的行数至少是查询结果中的10倍)

查询是否为那些不在这3列中的任何位置的数字返回一行零并不重要,因为缺少一个明确的和列(尽管我的偏好是它确实有总和不包括任何列中的列和数字。)

目前,我使用以下查询来获取未分组的数据:

SELECT * #Number, COUNT(DISTINCT A), COUNT(DISTINCT B), COUNT(DISTINCT C)
FROM
    ( # Generate a list of numbers to try
    SELECT @ROW := @ROW + 1 AS `Number`
    FROM DataTable t
    join (SELECT @ROW := -9) t2
    LIMIT 777 # None of the numbers I am interested in should be greater than this
    ) AS NumberList
INNER JOIN DataTable ON
    Number = A
    OR Number = B
    OR Number = C
    #WHERE <filters on DataTable columns to speed things up>
#WHERE NUMBER = 10 # speed things up
#GROUP BY Number

上面的查询将代码的注释部分保留为原样,返回一个类似于数据表的表,但按其匹配的条目号排序。我想将以相同Number开头的所有行组合在一起,并使查询结果的“数据”列中的值为相应列中Number出现次数的计数DataTable

当我取消注释分组语句(并从*语句中删除SELECT)时,我可以计算每个Number出现的行数(对{ {1}}所需输出的列)。但是,它并未向我提供sum匹配每个数据列的实际总数:我只获得了找到Number的行数的三个副本。 如何获取每个实际列的分组而不是匹配行的总数

此外,您可能已经注意到我有一些关于加快速度的评论。此查询,因此我添加了几个过滤器,因此测试运行速度更快。我非常希望某种方式让它快速运行,以便将查询结果从完整集发送到新表不是重用这些数据的唯一合理方法,因为我希望能够出于非性能原因,请使用Number上的过滤器。 是否有更好的方法来构建整体查询以使其运行得更快?

1 个答案:

答案 0 :(得分:2)

我认为你想要使用union all而不是聚合:

select number, sum(a) as a, sum(b) as b, sum(c) as c, count(*) as `sum`
from ((select a as number, 1 as a, 0 as b, 0 as c from t
      ) union all
      (select b, 0 as a, 1 as b, 0 as c from t
      ) union all
      (select c, 0 as a, 0 as b, 1 as c from t
      )
     ) abc
group by number
order by number;