在 MySQL 中一次汇总多个列

Summarise multiple columns at once in MySQL

我有一些数据(约 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"    |
+-----------+-----+-----+----+-----------+

我想输出 table 来计算每个数字在三列中出现的次数,例如:

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

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

查询 returns 是否在这 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

上面的查询,代码的注释部分保持原样 returns 一个 table 类似于数据 table,但按条目的编号排序它匹配。我想将所有以相同 Number 开头的行组合在一起,并将查询结果的 "data" 列中的值作为 NumberDataTable.

对应的列

当我取消注释分组语句(并从 SELECT 语句中删除 * 时),我可以计算每个 Number 出现的行数(对所需输出的 ​​sum 列)。但是,它并没有告诉我 Number 与每个数据列匹配的实际总数:我只得到了找到 Number 的行数的三个副本。 如何根据每个实际列而不是匹配行的总数进行分组


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

我想你想使用 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;