--- slug: /ja/sql-reference/aggregate-functions/grouping_function --- # GROUPING ## GROUPING [ROLLUP](../statements/select/group-by.md/#rollup-modifier) と [CUBE](../statements/select/group-by.md/#cube-modifier) は、GROUP BY に対する修飾子です。これらの修飾子は、いずれも小計を計算します。ROLLUP はカラムの並べられたリスト、例えば `(day, month, year)` を取り、集計の各レベルで小計を計算した後、総計を算出します。CUBE は、指定されたカラムの全ての可能な組み合わせにわたって小計を計算します。GROUPING は、ROLLUP または CUBE によって戻された行がスーパー集計であるかどうかを識別し、修飾されていない GROUP BY で戻される行であるかどうかを識別します。 GROUPING 関数は、複数のカラムを引数として受け取り、ビットマスクを返します。 - `1` は、`GROUP BY` に対する `ROLLUP` または `CUBE` 修飾子によって戻された行が小計であることを示します - `0` は、`ROLLUP` または `CUBE` によって戻された行が小計でないことを示します ## GROUPING SETS デフォルトでは、CUBE 修飾子は、CUBE に渡されたカラムのすべての可能な組み合わせに対して小計を計算します。GROUPING SETS を使用すると、計算する特定の組み合わせを指定できます。 階層データの分析には、ROLLUP、CUBE、および GROUPING SETS 修飾子を使用することがおすすめです。ここでのサンプルは、2つのデータセンターにインストールされている Linux ディストリビューションとそのバージョンに関するデータを含むテーブルです。このデータをディストリビューション、バージョン、および場所別で見ることが有益かもしれません。 ### サンプルデータのロード ```sql CREATE TABLE servers ( datacenter VARCHAR(255), distro VARCHAR(255) NOT NULL, version VARCHAR(50) NOT NULL, quantity INT ) ORDER BY (datacenter, distro, version) ``` ```sql INSERT INTO servers(datacenter, distro, version, quantity) VALUES ('Schenectady', 'Arch','2022.08.05',50), ('Westport', 'Arch','2022.08.05',40), ('Schenectady','Arch','2021.09.01',30), ('Westport', 'Arch','2021.09.01',20), ('Schenectady','Arch','2020.05.01',10), ('Westport', 'Arch','2020.05.01',5), ('Schenectady','RHEL','9',60), ('Westport','RHEL','9',70), ('Westport','RHEL','7',80), ('Schenectady','RHEL','7',80) ``` ```sql SELECT * FROM servers; ``` ```response ┌─datacenter──┬─distro─┬─version────┬─quantity─┐ │ Schenectady │ Arch │ 2020.05.01 │ 10 │ │ Schenectady │ Arch │ 2021.09.01 │ 30 │ │ Schenectady │ Arch │ 2022.08.05 │ 50 │ │ Schenectady │ RHEL │ 7 │ 80 │ │ Schenectady │ RHEL │ 9 │ 60 │ │ Westport │ Arch │ 2020.05.01 │ 5 │ │ Westport │ Arch │ 2021.09.01 │ 20 │ │ Westport │ Arch │ 2022.08.05 │ 40 │ │ Westport │ RHEL │ 7 │ 80 │ │ Westport │ RHEL │ 9 │ 70 │ └─────────────┴────────┴────────────┴──────────┘ 10 rows in set. Elapsed: 0.409 sec. ``` ### シンプルなクエリ ディストリビューションごとに各データセンターのサーバー数を取得: ```sql SELECT datacenter, distro, SUM (quantity) qty FROM servers GROUP BY datacenter, distro; ``` ```response ┌─datacenter──┬─distro─┬─qty─┐ │ Schenectady │ RHEL │ 140 │ │ Westport │ Arch │ 65 │ │ Schenectady │ Arch │ 90 │ │ Westport │ RHEL │ 150 │ └─────────────┴────────┴─────┘ 4 rows in set. Elapsed: 0.212 sec. ``` ```sql SELECT datacenter, SUM (quantity) qty FROM servers GROUP BY datacenter; ``` ```response ┌─datacenter──┬─qty─┐ │ Westport │ 215 │ │ Schenectady │ 230 │ └─────────────┴─────┘ 2 rows in set. Elapsed: 0.277 sec. ``` ```sql SELECT distro, SUM (quantity) qty FROM servers GROUP BY distro; ``` ```response ┌─distro─┬─qty─┐ │ Arch │ 155 │ │ RHEL │ 290 │ └────────┴─────┘ 2 rows in set. Elapsed: 0.352 sec. ``` ```sql SELECT SUM(quantity) qty FROM servers; ``` ```response ┌─qty─┐ │ 445 │ └─────┘ 1 row in set. Elapsed: 0.244 sec. ``` ### 複数の GROUP BY 文と GROUPING SETS の比較 CUBE、ROLLUP、または GROUPING SETS を使用せずにデータを分解: ```sql SELECT datacenter, distro, SUM (quantity) qty FROM servers GROUP BY datacenter, distro UNION ALL SELECT datacenter, null, SUM (quantity) qty FROM servers GROUP BY datacenter UNION ALL SELECT null, distro, SUM (quantity) qty FROM servers GROUP BY distro UNION ALL SELECT null, null, SUM(quantity) qty FROM servers; ``` ```response ┌─datacenter─┬─distro─┬─qty─┐ │ ᴺᵁᴸᴸ │ ᴺᵁᴸᴸ │ 445 │ └────────────┴────────┴─────┘ ┌─datacenter──┬─distro─┬─qty─┐ │ Westport │ ᴺᵁᴸᴸ │ 215 │ │ Schenectady │ ᴺᵁᴸᴸ │ 230 │ └─────────────┴────────┴─────┘ ┌─datacenter──┬─distro─┬─qty─┐ │ Schenectady │ RHEL │ 140 │ │ Westport │ Arch │ 65 │ │ Schenectady │ Arch │ 90 │ │ Westport │ RHEL │ 150 │ └─────────────┴────────┴─────┘ ┌─datacenter─┬─distro─┬─qty─┐ │ ᴺᵁᴸᴸ │ Arch │ 155 │ │ ᴺᵁᴸᴸ │ RHEL │ 290 │ └────────────┴────────┴─────┘ 9 rows in set. Elapsed: 0.527 sec. ``` GROUPING SETS を使用して同じ情報を取得: ```sql SELECT datacenter, distro, SUM (quantity) qty FROM servers GROUP BY GROUPING SETS( (datacenter,distro), (datacenter), (distro), () ) ``` ```response ┌─datacenter──┬─distro─┬─qty─┐ │ Schenectady │ RHEL │ 140 │ │ Westport │ Arch │ 65 │ │ Schenectady │ Arch │ 90 │ │ Westport │ RHEL │ 150 │ └─────────────┴────────┴─────┘ ┌─datacenter──┬─distro─┬─qty─┐ │ Westport │ │ 215 │ │ Schenectady │ │ 230 │ └─────────────┴────────┴─────┘ ┌─datacenter─┬─distro─┬─qty─┐ │ │ │ 445 │ └────────────┴────────┴─────┘ ┌─datacenter─┬─distro─┬─qty─┐ │ │ Arch │ 155 │ │ │ RHEL │ 290 │ └────────────┴────────┴─────┘ 9 rows in set. Elapsed: 0.427 sec. ``` ### CUBE と GROUPING SETS の比較 次のクエリにおける CUBE `CUBE(datacenter,distro,version)` は、意味をなさない階層を提供しています。2つのディストリビューションにわたってバージョンを見ることは意味をなさないかもしれません(なぜなら Arch と RHEL は同じリリースサイクルやバージョン命名標準を持っていないためです)。次の例で示すように、GROUPING SETS を使用すると、`distro` と `version` を同じセットでグループ化することができ、より適切です。 ```sql SELECT datacenter, distro, version, SUM(quantity) FROM servers GROUP BY CUBE(datacenter,distro,version) ORDER BY datacenter, distro; ``` ```response ┌─datacenter──┬─distro─┬─version────┬─sum(quantity)─┐ │ │ │ 7 │ 160 │ │ │ │ 2020.05.01 │ 15 │ │ │ │ 2021.09.01 │ 50 │ │ │ │ 2022.08.05 │ 90 │ │ │ │ 9 │ 130 │ │ │ │ │ 445 │ │ │ Arch │ 2021.09.01 │ 50 │ │ │ Arch │ 2022.08.05 │ 90 │ │ │ Arch │ 2020.05.01 │ 15 │ │ │ Arch │ │ 155 │ │ │ RHEL │ 9 │ 130 │ │ │ RHEL │ 7 │ 160 │ │ │ RHEL │ │ 290 │ │ Schenectady │ │ 9 │ 60 │ │ Schenectady │ │ 2021.09.01 │ 30 │ │ Schenectady │ │ 7 │ 80 │ │ Schenectady │ │ 2022.08.05 │ 50 │ │ Schenectady │ │ 2020.05.01 │ 10 │ │ Schenectady │ │ │ 230 │ │ Schenectady │ Arch │ 2022.08.05 │ 50 │ │ Schenectady │ Arch │ 2021.09.01 │ 30 │ │ Schenectady │ Arch │ 2020.05.01 │ 10 │ │ Schenectady │ Arch │ │ 90 │ │ Schenectady │ RHEL │ 7 │ 80 │ │ Schenectady │ RHEL │ 9 │ 60 │ │ Schenectady │ RHEL │ │ 140 │ │ Westport │ │ 9 │ 70 │ │ Westport │ │ 2020.05.01 │ 5 │ │ Westport │ │ 2022.08.05 │ 40 │ │ Westport │ │ 7 │ 80 │ │ Westport │ │ 2021.09.01 │ 20 │ │ Westport │ │ │ 215 │ │ Westport │ Arch │ 2020.05.01 │ 5 │ │ Westport │ Arch │ 2021.09.01 │ 20 │ │ Westport │ Arch │ 2022.08.05 │ 40 │ │ Westport │ Arch │ │ 65 │ │ Westport │ RHEL │ 9 │ 70 │ │ Westport │ RHEL │ 7 │ 80 │ │ Westport │ RHEL │ │ 150 │ └─────────────┴────────┴────────────┴───────────────┘ 39 rows in set. Elapsed: 0.355 sec. ``` :::note 上記の例のバージョンは、distro に関連していない場合には意味をなさないかもしれませんが、カーネルバージョンを追跡している場合には意味をなすかもしれません。なぜなら、カーネルバージョンはどちらのディストリビューションにも関連付けられる可能性があるからです。次の例のように GROUPING SETS を使用する方が適している場合があります。 ::: ```sql SELECT datacenter, distro, version, SUM(quantity) FROM servers GROUP BY GROUPING SETS ( (datacenter, distro, version), (datacenter, distro)) ``` ```response ┌─datacenter──┬─distro─┬─version────┬─sum(quantity)─┐ │ Westport │ RHEL │ 9 │ 70 │ │ Schenectady │ Arch │ 2022.08.05 │ 50 │ │ Schenectady │ Arch │ 2021.09.01 │ 30 │ │ Schenectady │ RHEL │ 7 │ 80 │ │ Westport │ Arch │ 2020.05.01 │ 5 │ │ Westport │ RHEL │ 7 │ 80 │ │ Westport │ Arch │ 2021.09.01 │ 20 │ │ Westport │ Arch │ 2022.08.05 │ 40 │ │ Schenectady │ RHEL │ 9 │ 60 │ │ Schenectady │ Arch │ 2020.05.01 │ 10 │ └─────────────┴────────┴────────────┴───────────────┘ ┌─datacenter──┬─distro─┬─version─┬─sum(quantity)─┐ │ Schenectady │ RHEL │ │ 140 │ │ Westport │ Arch │ │ 65 │ │ Schenectady │ Arch │ │ 90 │ │ Westport │ RHEL │ │ 150 │ └─────────────┴────────┴─────────┴───────────────┘ 14 rows in set. Elapsed: 1.036 sec. ```