CASE 式と GROUP BY 句によるピボット処理
SQLite におけるピボット処理
SQLite では、PIVOT 関数は公式にサポートされていません。しかし、いくつかの方法でピボット処理を実行することができます。
方法
- CASE 式と GROUP BY 句
最も基本的な方法は、CASE 式と GROUP BY 句を組み合わせる方法です。
SELECT
category,
SUM(CASE WHEN month = 1 THEN amount END) AS amount_1,
SUM(CASE WHEN month = 2 THEN amount END) AS amount_2,
...
FROM sales
GROUP BY category;
このクエリは、sales
テーブルからカテゴリ別の売上を集計し、月ごとの売上を列として表示します。
- 動的 SQL
動的 SQL を使用して、ピボット処理を実行することもできます。これは、より複雑なピボット処理に適しています。
DECLARE @sql NVARCHAR(MAX);
SET @sql = '
SELECT
category,
' + STUFF((
SELECT DISTINCT ',' + CONCAT('[', month, ']', ' = SUM(CASE WHEN month = ', month, ' THEN amount END)')
FROM sales
FOR XML PATH(''), TYPE
).value('NVARCHAR(MAX)'), 1, 1, '') + '
FROM sales
GROUP BY category;
';
EXEC sp_executesql @sql;
- 拡張モジュール
SQLite には、ピボット処理を可能にするいくつかの拡張モジュールが用意されています。
これらの拡張モジュールを使用すると、より柔軟なピボット処理を実行することができます。
注意点
- 上記の方法は、いずれも SQLite の標準機能ではありません。
- 動的 SQL や拡張モジュールを使用する場合は、セキュリティ上のリスクに注意する必要があります。
上記の解説に加えて、以下の点にも注意する必要があります。
- ピボット処理を実行する前に、データが適切に正規化されていることを確認する必要があります。
- ピボット処理は、データの量が多い場合に時間がかかることがあります。
- ピボット処理の結果は、元のデータとは異なる形式になります。
-- sales テーブルを作成
CREATE TABLE sales (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT,
month INTEGER,
amount REAL
);
-- sales テーブルにデータを入力
INSERT INTO sales (category, month, amount) VALUES
('A', 1, 100),
('A', 2, 200),
('A', 3, 300),
('B', 1, 400),
('B', 2, 500),
('B', 3, 600);
-- カテゴリ別の売上を集計し、月ごとの売上を列として表示
SELECT
category,
SUM(CASE WHEN month = 1 THEN amount END) AS amount_1,
SUM(CASE WHEN month = 2 THEN amount END) AS amount_2,
SUM(CASE WHEN month = 3 THEN amount END) AS amount_3
FROM sales
GROUP BY category;
出力
category | amount_1 | amount_2 | amount_3
------- | -------- | -------- | --------
A | 100 | 200 | 300
B | 400 | 500 | 600
-- sales テーブルを作成
-- (サンプルコード 1と同じ)
-- 動的 SQL を使用してピボット処理を実行
DECLARE @sql NVARCHAR(MAX);
SET @sql = '
SELECT
category,
' + STUFF((
SELECT DISTINCT ',' + CONCAT('[', month, ']', ' = SUM(CASE WHEN month = ', month, ' THEN amount END)')
FROM sales
FOR XML PATH(''), TYPE
).value('NVARCHAR(MAX)'), 1, 1, '') + '
FROM sales
GROUP BY category;
';
EXEC sp_executesql @sql;
category | [1] | [2] | [3]
------- | -------- | -------- | --------
A | 100 | 200 | 300
B | 400 | 500 | 600
SQLite Pivot Table Extension
- SQLite Pivot Table Extension をダウンロードしてインストールします。
- 以下のクエリを実行します。
-- sales テーブルを作成
-- (サンプルコード 1と同じ)
-- SQLite Pivot Table Extension を使用してピボット処理を実行
SELECT *
FROM sales
PIVOT (
SUM(amount)
FOR month IN (1, 2, 3)
) AS pivot_table;
category | 1 | 2 | 3
------- | -------- | -------- | --------
A | 100 | 200 | 300
B | 400 | 500 | 600
SQLite FTS5 Extension
-- sales テーブルを作成
-- (サンプルコード 1と同じ)
-- SQLite FTS5 Extension を使用してピボット処理を実行
ATTACH DATABASE 'fts5.db' AS fts;
CREATE VIRTUAL TABLE sales_fts5 USING fts5(
id INTEGER,
category TEXT,
month INTEGER,
amount REAL
);
INSERT INTO sales_fts5 SELECT * FROM sales;
SELECT *
FROM sales_fts5
WHERE category MATCH ?
GROUP BY category
PIVOT (
SUM(amount)
FOR month IN (1, 2, 3)
) AS pivot_table;
category | 1 | 2 | 3
------- | -------- | -------- | --------
A | 100 | 200 | 300
B | 400 | 500 | 600
- サブクエリ
- ウィンドウ関数
- クロス集約
- サードパーティ製ライブラリ
詳細
サブクエリを使用すると、より複雑なピボット処理を実行することができます。
SELECT
category,
(SELECT SUM(amount) FROM sales WHERE month = 1) AS amount_1,
(SELECT SUM(amount) FROM sales WHERE month = 2) AS amount_2,
...
FROM sales
GROUP BY category;
SELECT
category,
SUM(amount) OVER (PARTITION BY category, month ORDER BY month) AS amount
FROM sales;
SELECT
category,
month,
SUM(amount)
FROM sales
CROSS JOIN (
SELECT DISTINCT month
FROM sales
) AS months
GROUP BY category, month;
- サブクエリ、ウィンドウ関数、クロス集約を使用する場合は、パフォーマンスに影響を与える可能性があります。
- サードパーティ製ライブラリを使用する場合は、セキュリティ上のリスクに注意する必要があります。
これらの方法は、より複雑なピボット処理に適しています。
sql sqlite pivot