8

我有一个这样的表结构:

CREATE TABLE `test` (
  `a` tinyint(3) unsigned DEFAULT 0,
  `b` tinyint(3) unsigned DEFAULT 0,
   `c` tinyint(3) unsigned DEFAULT 0,
  `d` tinyint(3) unsigned DEFAULT 0,
  `e` tinyint(3) unsigned DEFAULT 0
  );

这有大约 30 列,其中一些列的值从 0-200 (a,b) 和一些只有 5 个值 (0,1,2,3,4)(列 cd)。大约有。表中有 120k 行。

为了显示每行的项目数,我对每一列使用查询:

select a, count(*) FROM test group by a;
select b, count(*) FROM test group by b;
select c, count(*) FROM test group by c;
select d, count(*) FROM test group by d;
select e, count(*) FROM test group by e;

这样做的问题是它将触发 30 个查询(每列一个),并且每次基本上都会遍历同一组数据。

有一个更好的方法吗?

我已经尝试过使用 GROUP BY WITH ROLLUP 但这会导致结果集比每个单独的查询处理得慢。

您可以查看 SQLfiddle 上的数据选择:http ://sqlfiddle.com/#!2/a9fd8/1

4

5 回答 5

3
select 'a' as `column`, a as data, count(*) 
FROM test 
group by 'a', a
union
select 'b', b, count(*) 
FROM test 
group by 'b', b
union
select 'c', c, count(*) 
FROM test 
group by 'c', c
union
select 'd', d, count(*) 
FROM test 
group by 'd', d
union
select 'e', e, count(*) 
FROM test 
group by 'e', e

不知道它是否更好,但至少规划者将有机会对其进行优化。

于 2012-09-21T12:08:20.697 回答
2

也许这样的事情会更快。

select qq, q, count(*) from
(
select 'a' qq, a q FROM test
union all select 'b' qq, b q FROM test
union all select 'c' qq, c q FROM test
union all select 'd' qq, d q FROM test
union all select 'e' qq, e q FROM test
) t
group by qq, q;
于 2012-09-24T11:44:35.430 回答
1

编辑:这个答案完全偏离了轨道

尝试以下操作;这是一个更简洁的查询,只需通过一次,但由于 DISTINCT,我不确定它的性能如何:

SELECT 
  COUNT(DISTINCT a) AS a,
  COUNT(DISTINCT b) AS b,
  COUNT(DISTINCT c) AS c,
  COUNT(DISTINCT d) AS d,
FROM
  t
;
于 2012-09-27T11:31:34.933 回答
0

根据这里的生态,建立一个聚合数据表可能更有效,然后在修改该表时保持最新。您的聚合数据表将为每个(当前)值包含一行,然后是 30 个额外的计数列。然后,您可以在更新计数的原件上放置触发器。当然,这会减慢原始表上的写入操作,尽管添加 30 个索引也会如此。

于 2012-10-01T06:29:47.423 回答
0

没有什么原创的,但你可以试试这个。

SELECT t.col, t.val, t.c FROM
(
    SELECT 'a' col, a val, count(*) c FROM test GROUP BY a
    UNION ALL
    SELECT 'b' col, b val, count(*) c FROM test GROUP BY b
    UNION ALL
    SELECT 'c' col, c val, count(*) c FROM test GROUP BY c
    UNION ALL
    SELECT 'd' col, d val, count(*) c FROM test GROUP BY d
    UNION ALL
    SELECT 'e' col, e val, count(*) c FROM test GROUP BY e
) t

但是,如果这里的性能有问题,我想建议@edze 建议的同样的事情 - 列索引(是的,所有 30)。它会占用空间,但会提高性能。甚至创建视图表

CREATE TABLE `test_view` (
   `col` char(1), 
   `value` tinyint(3), 
   `count` int
);

对于此任务,如果经常执行,则只需执行简单的选择即可。

于 2012-09-28T12:34:52.957 回答