CREATE TABLE Item (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
status TINYINT
);
こんな感じの数値のステータスを持つテーブルがあったとして、status=0が未処理、status=1が処理中、status=3が処理済みという意味だとする。それぞれのstatusのItemの数を取得するには、以下のようなクエリを書けばいい。
SELECT status, COUNT(0) as count FROM Item
GROUP BY status
ORDER BY status;
+--------+-------+
| status | count |
+--------+-------+
| 0 | 1 |
| 1 | 3 |
| 2 | 2 |
+--------+-------+
結果はこのようになるが、ここでstatusを「未処理」「処理中」「処理済み」のようなわかりやすい表記にしたい。
一般的な解決方法としては、ENUM型を使うことが挙げられる。しかし、ENUM型は0が空文字列、1以降が列挙値であり、0に列挙値を指定することができない。既に0番が定義されているならばTINYINTをENUMに変更しない方がいい。
ちなみにstatusが1から始まってる場合は以下のようになる。
ALTER TABLE Item CHANGE COLUMN status status ENUM('未処理', '処理中', '処理済み');
SELECT status, COUNT(0) as count FROM Item
GROUP BY status
ORDER BY status;
+--------------+-------+
| status | count |
+--------------+-------+
| 未処理 | 1 |
| 処理中 | 3 |
| 処理済み | 2 |
+--------------+-------+
statusの値や型を変えずに出力のみ「未処理」などのラベルにするために、MAKE_SET関数を利用してみた。
MAKE_SET関数は第1引数にbitを指定し、第2引数以降でマッチするものをカンマ区切りで返す関数。例えば、bitが1なら第2引数のみが、bitが5なら第2引数と第4引数が返る。
これを使い、第一引数に2のstatus乗を指定することで、statusが0なら第2引数、statusが1なら第3引数...というような値を得ることができる。
SELECT
MAKE_SET(POW(2, status),'未処理','処理中','処理済み') as status,
COUNT(0) as count
FROM Item
GROUP BY Item.status
ORDER BY Item.status;
+--------------+-------+
| status | count |
+--------------+-------+
| 未処理 | 1 |
| 処理中 | 3 |
| 処理済み | 2 |
+--------------+-------+
もう少し普通の方法があれば教えてください。