SQL ServerでGROUPING演算子を使ってPostgreSQL、MySQLと比較してみた。
はじめに
前回のSQL Serverでウィンドウ関数を使ってみた。に続いてGROUPING演算子なるものに遭遇しました。 どうやら簡単に合計と小計を算出す事ができるらしく、使えると便利かなと思い調べてみました。
構文
グループ分けしたいカラム名を SELECT句 と GROUP BY句 の ROLLUP句 に入れます。
SELECT カラム名1, カラム名2, ..., SUM(算出するカラム名) FROM テーブル名 GROUP BY ROLLUP(カラム名1, カラム名2, ...);
用意したテーブル
ureyuki
何の種類の本を、いつ、男女どちらが、何冊購入したかを示す表です。
id | shurui | ure_date | seibetsu | ure_su ----+--------------+------------+----------+-------- 1 | まんが | 2016-02-01 | 男 | 4 2 | まんが | 2016-02-02 | 男 | 1 3 | まんが | 2016-02-02 | 女 | 2 4 | 情報誌 | 2016-02-05 | 男 | 2 5 | 情報誌 | 2016-02-03 | 女 | 2 6 | ファッション | 2016-02-03 | 男 | 1 7 | ファッション | 2016-02-04 | 女 | 1
使用例1
出力したい結果
テーブル ureyuki の shurui ごとに ures_su の合計と全体の ure_su の合計を表示しています。 順番は「合計が上段」「それ以外が下段」と分かれていれば良しとします。
shurui | sum_su --------------+-------- | 13 <- ure_suの合計 まんが | 7 情報誌 | 4 ファッション | 2
使用するSQLごとのSQL文
・SQL Server
SELECT shurui, SUM(ure_su) FROM ureyuki GROUP BY ROLLUP(shurui) ORDER BY shurui;
・MySQL SQL Server の様に ORDER BY句 が使えないのでサブクエリ化してから ORDER BY句 で並び替えます。
SELECT * FROM ( SELECT shurui, SUM(ure_su) sum_su FROM ureyuki GROUP BY shurui WITH ROLLUP ) SQ ORDER BY shurui;
・PostgreSQL ROLLUP が使えないので UNION ALL で合計と小計を繫げます。
SELECT '' shurui, SUM(shiire_su) sum_su FROM ureyuki UNION ALL SELECT shurui, SUM(shiire_su) sum_su FROM ureyuki GROUP BY shurui;
使用例2
出力したい結果
今度は seibetsu ごとも含めてみます。
shurui | seibetsu | sum --------------+----------+----- | | 13 <- 総合計 まんが | | 7 <- まんがの合計 まんが | 男 | 5 まんが | 女 | 2 情報誌 | | 4 <- 情報誌の合計 情報誌 | 男 | 2 情報誌 | 女 | 2 ファッション | | 2 <- ファッションの合計 ファッション | 男 | 1 ファッション | 女 | 1
使用するSQLごとのSQL文
・SQL Server SELECT句、GROUP BY句、ORDER BY句に seibetsu を追加しただけです。
SELECT shurui, seibetsu, SUM(ure_su) FROM ureyuki GROUP BY ROLLUP(shurui , seibetsu) ORDER BY shurui, seibetsu;
・MySQL こちらもほぼ同じです。
SELECT * FROM (SELECT shurui, seibetsu, SUM(ure_su)su FROM ureyuki GROUP BY shurui, seibetsu WITH ROLLUP) SQ ORDER BY shurui, seibetsu;
・PostgreSQL version 9.4までは ROLLUP が使えないのでひたすら UNION ALL で下記の順に繫げます。 1、全体の合計を算出 UNION ALL 2、shurui'まんが'の 合計を算出 UNION ALL 3、shurui'まんが'の seibetsu ごとを算出 UNION ALL 4、shurui'情報誌'の 合計を算出 UNION ALL 5、shurui'情報誌'の seibetsu ごとを算出 UNION ALL 6、shurui'ファッション'の 合計を算出 UNION ALL 7、shurui'ファッション'の seibetsu ごとを算出
SELECT '' shurui, '' seibetsu, SUM(ure_su) FROM ureyuki UNION ALL SELECT 'まんが' shurui, '' seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='まんが' UNION ALL SELECT shurui, seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='まんが' GROUP BY shurui, seibetsu UNION ALL SELECT '情報誌' shurui, '' seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='情報誌' UNION ALL SELECT shurui, seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='情報誌' GROUP BY shurui, seibetsu UNION ALL SELECT 'ファッション' shurui, '' seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='ファッション' UNION ALL SELECT shurui, seibetsu, SUM(ure_su) FROM ureyuki WHERE shurui='ファッション' GROUP BY shurui, seibetsu;
...PostgreSQLが嫌になりますね。 実際にこんな形の表を作るかは別ですが。
2016年2月24日 追記
読者の方からPostGreSQLの最新バージョンでGROUPING:ROLLUPがサポートされていますという有益なご指摘を頂きましたので、実際にversion 9.5.1をインストールして動作確認することができましたのでその内容も合わせてアップしておきたいと思います。
ROLLUP
使用例1のSQL文
SELECT shurui, SUM(ure_su) FROM ureyuki GROUP BY ROLLUP(shurui) ORDER BY shurui DESC;
実行結果
shurui | sum --------------+----- | 13 情報誌 | 4 ファッション | 2 まんが | 7
使用例2のSQL文
SELECT shurui, seibetsu, SUM(ure_su) FROM ureyuki GROUP BY ROLLUP(shurui , seibetsu) ORDER BY shurui DESC, seibetsu DESC;
実行結果
shurui | seibetsu | sum --------------+----------+----- | | 13 情報誌 | | 4 情報誌 | 男 | 2 情報誌 | 女 | 2 ファッション | | 2 ファッション | 男 | 1 ファッション | 女 | 1 まんが | | 7 まんが | 男 | 5 まんが | 女 | 2
使用例1、使用例2のどちらも同じような結果が出せましたが、並び順が違ったので ORDER BY句 で shurui DESC としました。 PostgreSQLも進化していますね。
さいごに
最初はSQL Serverとの違いを知りたかっただけでしたが、目的によってはSQL文がだいぶ面倒になる事が分かりました。 利用しているSQLで何ができるのか、しっかり理解していると仕事が捗りそうですね。