【问题标题】:Summarise multiple columns at once in MySQL在 MySQL 中一次汇总多个列
【发布时间】: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开头的行组合在一起,并将查询结果的“数据”列中的值作为NumberDataTable的相应列中出现的次数的计数.

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


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

【问题讨论】:

    标签: mysql performance group-by grouping counting


    【解决方案1】:

    我认为您想使用 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;
    

    【讨论】:

    • 这很好用!看起来我需要包含我认为自己从t 过滤三次的列,但我可以在分组和排序上方使用WHERE 过滤器。有没有办法对有限但未知数量的列执行此操作,或者如果我遇到这种情况,非 SQL 数据库(可能是 3-D 数据库)会成为更好的工具吗?
    猜你喜欢
    • 2019-01-17
    • 1970-01-01
    • 2021-01-18
    • 2021-10-27
    • 1970-01-01
    • 2013-04-20
    • 2018-02-28
    • 2021-04-28
    • 2019-05-11
    相关资源
    最近更新 更多