【发布时间】:2017-07-28 12:25:13
【问题描述】:
我有一些数据(约 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 出现的行数(对于所需的sum 列很有用输出)。但是,它并没有给出Number 匹配每个数据列的实际总数:我只得到了找到Number 的行数的三个副本。 如何按每个实际列而不是匹配行的总数进行分组?
此外,您可能已经注意到我与 cmets 有一些关于加快速度的说法。这个查询慢,所以我添加了几个过滤器以便测试它运行得更快。我非常想要一些让它运行得更快的方法,以便将查询结果从完整集发送到新表并不是重用这些数据的唯一合理方法,因为我希望能够出于非性能原因,在DataTable 上使用过滤器。 有没有更好的方法来构建整个查询以使其运行得更快?
【问题讨论】:
标签: mysql performance group-by grouping counting