从mysql中获取许多分组值

时间:2012-09-21 11:57:35

标签: mysql performance group-by

我有一个像这样的表结构:

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)(列c-d)。有aprox。表中有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

5 个答案:

答案 0 :(得分: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

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

答案 1 :(得分: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;

答案 2 :(得分: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
;

答案 3 :(得分: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
);

执行此任务,然后只需执行简单选择是否经常执行。

答案 4 :(得分:0)

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