8

I have a table structure like this:

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
  );

This has about 30 columns with some columns that have values from 0-200 (a,b) and some only have 5 values (0,1,2,3,4) (column c-d). There are aprox. 120k rows in the table.

To show the number of items per row I use a query for each column:

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;

The problem with this is that it will fire 30 queries (one per column) and basically goes over the same set of data each time.

Is there a better way to do this?

I have tried with GROUP BY WITH ROLLUP but this results in a massive resultset which is slower to process than each individual query.

You can view a selection of the data on 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

編集:この答えは完全に軌道に乗っていない

次のことを試してください。これは、パスが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

オリジナルはありませんが、これを試すことができます。

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 に答える
0

ここでのエコロジーによっては、集合体データのテーブルを一度作成してから、このテーブルが変更されるたびに最新の状態に保つ方が効率的な場合があります。集合体データテーブルには、(現在の)値ごとに1つの行があり、さらに30列のカウントがあります。次に、カウントを更新するトリガーをオリジナルに配置できます。当然、これにより元のテーブルへの書き込み操作が遅くなりますが、30個のインデックスが追加されます。

于 2012-10-01T06:29:47.423 に答える