我有一个像这样的表结构:
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
答案 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个索引。