3. 第6回 PostgreSQLアンカンファレンス 3/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ こんな売上実績データ(result表、item表、shop表をJOIN)
SELECT r_date::date date,s_name,i_name,r_qt,r_qt * i_price sales
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
ORDER BY r_date;
r_date | s_name | i_name | r_qt | sales
------------+------------+--------------+------+--------
2015-10-30 | Paul Smith | スラックス | 1 | 20000
2015-10-30 | Dior | シャツ | 2 | 60000
2015-10-30 | Dior | 冬ジャケット | 1 | 100000
2015-10-30 | Paul Smith | シャツ | 1 | 15000
2015-10-31 | DIESEL | ダメージB | 1 | 35000
2015-10-31 | DIESEL | ストレート | 2 | 50000
2015-10-31 | Dior | 冬ジャケット | 1 | 100000
2015-10-31 | Dior | シャツ | 1 | 30000
2015-11-01 | Paul Smith | シャツ | 3 | 45000
2015-11-02 | DIESEL | ダメージA | 1 | 30000
4. 第6回 PostgreSQLアンカンファレンス 4/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ 日別の売上集計と店舗毎の売り上げ集計が欲しい
SELECT r_date::date date
,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY date ORDER BY sum DESC;
date | sum
------------+--------
2015-10-31 | 215000
2015-10-30 | 195000
2015-11-08 | 50000
2015-11-01 | 45000
2015-11-03 | 45000
2015-11-02 | 45000
2015-11-07 | 40000
2015-11-06 | 30000
:
SELECT s_name shop
,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY shop ORDER BY sum DESC;
shop | sum
------------+--------
Dior | 350000
DIESEL | 195000
Paul Smith | 165000
(3 行)
5. 第6回 PostgreSQLアンカンファレンス 5/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● GROUP BY GROUPING SETS
✔ 1クエリで店舗別、日別、総計を取得
SELECT s_name shop,r_date::date date,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY GROUPING SETS ((shop),(date),());
shop | date | sum
------------+------------+--------
DIESEL | | 195000
Dior | | 350000
Paul Smith | | 165000
| | 710000 /*総計*/
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-01 | 45000
| 2015-11-02 | 45000
| 2015-11-03 | 45000
:
6. 第6回 PostgreSQLアンカンファレンス 6/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● ROLLUP
✔ 1クエリで店舗-日付の組合せ、店舗別売上、総計を取得
SELECT s_name shop,r_date::date date
,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY ROLLUP ((shop),(date));
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | 2015-11-06 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-10-31 | 130000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | | 165000
| | 710000
(結果はスライド用にところどころ省略)
7. 第6回 PostgreSQLアンカンファレンス 7/21
標準SQLへの対応
1クエリで複数の集計を組合せて取得
● CUBE
✔ 1クエリで店舗-日付の組合せ、店舗別売上、日別売上、総計を取得
SELECT s_name shop,r_date::date date
,sum(r_qt * i_price) sum
FROM result
JOIN item ON r_item = i_code
JOIN shop ON i_shop = s_id
GROUP BY CUBE ((shop),(date));
shop | date | sum
------------+------------+--------
DIESEL | 2015-10-31 | 85000
DIESEL | 2015-11-02 | 30000
DIESEL | | 195000
Dior | 2015-10-30 | 160000
Dior | 2015-11-08 | 30000
Dior | | 350000
Paul Smith | 2015-10-30 | 35000
Paul Smith | 2015-11-01 | 45000
Paul Smith | 2015-11-02 | 15000
Paul Smith | 2015-11-08 | 20000
Paul Smith | | 165000
| | 710000
| 2015-10-30 | 195000
| 2015-10-31 | 215000
| 2015-11-08 | 50000
(結果はスライド用にところどころ省略)
17. 第6回 PostgreSQLアンカンファレンス 17/21
実用シーンを考察
クロス集計までDBで完結する
● クロス集計
✔ tablefuncエクステンションでクロス集計
--CUBE結果をMViewに保存(tablefuncの構文をシンプルにしたいので今回はコレで。)
CREATE MATERIALIZED VIEW mv_cube AS
SELECT sales_date::date,shop,kind,count(*) FROM result
GROUP BY CUBE ((sales_date::date),(shop),(kind));
--crosstab関数をかませて結果を整形
SELECT * FROM crosstab('
SELECT date,COALESCE(shop,''null''),sum FROM mv_cube --整形したいクエリ
ORDER BY date
','
SELECT DISTINCT COALESCE(shop,''null'') shop FROM mv_cube --2番目の引数は
ORDER BY shop NULLS LAST --結果の列名に対応
')
AS sales (
date date
,"DIESEL" numeric
,"Dior" numeric
,"Paul Smith" numeric
,"daily sum" numeric
);