やりたいことは、SQL 構文では直接サポートされていないピボット操作です。ただし、それほど複雑ではなく、概念的には次の 2 つの手順が含まれます。
- 元のデータ セットの行ごとに 1 つの行で、データを多くの列に "爆破" します。これは通常、CASE WHEN ... ELSE ... END で行われるか、場合によっては関数 (Oracle の decode() など) で行われます。以下の例では CASE WHEN を使用します。これは、ほとんどの RDBMS で同様に機能するためです。
- GROUP BY と集計関数 (SUM、MIN、MAX など) を使用して、多数の行を必要な出力行セットにまとめます。
例として、次のデータセットを使用しています。
mysql> select * from foo;
+------+------+---------+
| uid | id | type |
+------+------+---------+
| 1 | 1 | product |
| 1 | 2 | product |
| 1 | 3 | service |
| 1 | 4 | product |
| 1 | 5 | product |
| 2 | 6 | service |
| 1 | 7 | order |
| 2 | 8 | invoice |
| 2 | 9 | product |
+------+------+---------+
ステップ 1 は、データ セットを「爆破」することです。
select uid
, case when type = 'product' then 1 else 0 end as is_product
, case when type = 'service' then 1 else 0 end as is_service
, case when type = 'invoice' then 1 else 0 end as is_invoice
, case when type = 'order' then 1 else 0 end as is_order
from foo;
与える:
+------+------------+------------+------------+----------+
| uid | is_product | is_service | is_invoice | is_order |
+------+------------+------------+------------+----------+
| 1 | 1 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 |
| 2 | 0 | 1 | 0 | 0 |
| 1 | 0 | 0 | 0 | 1 |
| 2 | 0 | 0 | 1 | 0 |
| 2 | 1 | 0 | 0 | 0 |
+------+------------+------------+------------+----------+
次に、日付ごとに出力を 1 行にまとめ、インライン ビュー (別名「サブクエリ」) として初期クエリを使用して、各 is_* 列を合計します。
select uid
, sum(is_product) as count_product
, sum(is_service) as count_service
, sum(is_invoice) as count_invoice
, sum(is_order) as count_order
from (
select uid
, case when type = 'product' then 1 else 0 end as is_product
, case when type = 'service' then 1 else 0 end as is_service
, case when type = 'invoice' then 1 else 0 end as is_invoice
, case when type = 'order' then 1 else 0 end as is_order
from foo
) x
group by uid;
(ここではわかりやすくするために別々に示していますが、これら 2 つのクエリを 1 つにまとめることができることにも注意してください。少なくとも MySQL では、これにより実行プランが単純になり、多くの場合、実行が高速になります。いつものように、テスト現実的なデータ セットでの SQL パフォーマンス、私の言葉を鵜呑みにしないでください!)
これにより、次のことがわかります。
+------+---------------+---------------+---------------+-------------+
| uid | count_product | count_service | count_invoice | count_order |
+------+---------------+---------------+---------------+-------------+
| 1 | 4 | 1 | 0 | 1 |
| 2 | 1 | 1 | 1 | 0 |
+------+---------------+---------------+---------------+-------------+
これは望ましい結果です。