PostgreSQL 9.5:新機能 パート3.グループ化セット、キューブ、ロールアップ

PostgreSQL 9.5の新機能に引き続き精通しています。

パート1.衝突しないでください/更新と行レベルのセキュリティ

パート2. TABLESAMPLE

今日は、1つのクエリで複数のグループ化を検討します。 この機能は、SQL-99標準で説明されています。 GROUP BYの条件が異なるだけで、同じテーブルに対して複数のクエリを作成する必要がある場合に使用すると便利です。 このため、 GROUPING SETS、ROLLUP、CUBE修飾子は、 GROUP BYキーワードの後にグループ化要素として示されます。

これがどのように機能するかを詳しく見てみましょう。



支払いに関するデータがあるスキームがあり、各支払いにはタイプ、この支払いが行われた都市、および支払い額があるとします。 都市には必ず国があり、オプションで地域があります。 以下は、そのようなスキームを作成し、データを入力するためのリクエストです。

スキーマ作成
DROP TABLE IF EXISTS payment; DROP TABLE IF EXISTS payment_type; DROP TABLE IF EXISTS city; DROP TABLE IF EXISTS state; DROP TABLE IF EXISTS country; CREATE TABLE country ( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL ); CREATE TABLE state ( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, country_id INT REFERENCES country (id) ); CREATE TABLE city ( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, state_id INT NULL REFERENCES state (id), country_id INT NOT NULL REFERENCES country (id), population BIGINT NOT NULL ); CREATE TABLE payment_type ( id SERIAL PRIMARY KEY, name VARCHAR NOT NULL ); CREATE TABLE payment ( id BIGSERIAL PRIMARY KEY, payment_type_id INT NOT NULL REFERENCES payment_type (id), city_id INT NOT NULL REFERENCES city (id), amount NUMERIC(10, 2) NOT NULL ); INSERT INTO country (name) VALUES ('Russia'), ('Ukraine'); INSERT INTO state (name, country_id) VALUES ('Moscow region', 1), ('Samara region', 1), ('Kursk region', 1), ('Tatarstan', 1), ('Kiev region', 2), ('Lugansk region', 2), ('Lvov region', 2), ('Odessa region', 2); –-          ,      INSERT INTO city (name, state_id, country_id, population) VALUES ('Moscow', NULL, 1, 12197596), ('Dubna', 1, 1, 75176), ('Samara', 2, 1, 1171820), ('Tolyatti', 2, 1, 719646), ('Syzran', 2, 1, 175222), ('Novokuybyshevsk', 2, 1, 105007), ('Kursk', 3, 1, 435117), ('Kazan', 4, 1, 1205651), ('Kiev', NULL, 2, 2888470), ('Irpen', 5, 2, 39972), ('Borispol', 5, 2, 60102), ('Belaya Tserkov', 5, 2, 211205), ('Lugansk', 6, 2, 417990), ('Lisichansk', 6, 2, 103459), ('Severodonetsk', 6, 2, 108899), ('Popasnaya', 6, 2, 21765), ('Lvov', 7, 2, 729038), ('Drogobych', 7, 2, 76866), ('Odessa', 8, 2, 1017022), ('Izmail', 8, 2, 72501); INSERT INTO payment_type (name) VALUES ('Online'), ('Box office'), ('Terminal'); INSERT INTO payment (payment_type_id, city_id, amount) SELECT ceil(random() * 3), ceil(random() * 20), trunc(cast(random() * 10000 AS NUMERIC), 2) FROM generate_series(1, 10000);
      
      







各都市および各国の支払い額に関する統計を取得するとします。 以前は、このために次の形式のクエリを作成する必要がありました。

 (SELECT sum(amount), c.country_id, NULL as city_id FROM payment AS p INNER JOIN city AS c ON p.city_id=c.id GROUP BY c.country_id ORDER BY c.country_id) UNION ALL (SELECT sum(amount), NULL, p.city_id FROM payment AS p GROUP BY p.city_id ORDER BY p.city_id)
      
      





クエリ結果
合計 country_id city_id
19794121.93 1 ヌル
30138426.57 2 ヌル
2420939.72 ヌル 1
2611787.51 ヌル 2
2357570.54 ヌル 3
2796471.48 ヌル 4
2327588.11 ヌル 5
2563701.69 ヌル 6
2442654.38 ヌル 7
2273408.5 ヌル 8
2509228.24 ヌル 9
2716771.77 ヌル 10
2745394.99 ヌル 11
2554721.34 ヌル 12
2526112.36 ヌル 13
2818708.34 ヌル 14
2437768.84 ヌル 15
2246483.68 ヌル 16
2384795.14 ヌル 17
2437849.05 ヌル 18
2470876.07 ヌル 19
2289716.75 ヌル 20




バージョン9.5以降、同様のリクエストは次のように書く方が簡単です。

 SELECT sum(amount), c.country_id, p.city_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(c.country_id, p.city_id);
      
      





クエリ結果
合計 country_id city_id
19794121.93 1 ヌル
30138426.57 2 ヌル
2420939.72 ヌル 1
2611787.51 ヌル 2
2357570.54 ヌル 3
2796471.48 ヌル 4
2327588.11 ヌル 5
2563701.69 ヌル 6
2442654.38 ヌル 7
2273408.5 ヌル 8
2509228.24 ヌル 9
2716771.77 ヌル 10
2745394.99 ヌル 11
2554721.34 ヌル 12
2526112.36 ヌル 13
2818708.34 ヌル 14
2437768.84 ヌル 15
2246483.68 ヌル 16
2384795.14 ヌル 17
2437849.05 ヌル 18
2470876.07 ヌル 19
2289716.75 ヌル 20




ご覧のとおり、クエリの結果としてのGROUPING SETSは、次のようにデータを返します。括弧内にリストされた列の1つの各行には値があり、残りの列(括弧内のリストから)はNULLで埋められます。 GROUPING SETSリストされていない列は、通常どおり計算されます。



(グループ化せずに)全額を取得するには、空のグループ化- ()を使用できます。 グループ化が空の場合、 GROUPING SETSに参加しているすべてのフィールドにNULL 入力されます。

 SELECT sum(amount), p.city_id, c.country_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, C.country_id, ());
      
      





クエリ結果
合計 country_id city_id
19794121.93 1 ヌル
30138426.57 2 ヌル
49932548.5 ヌル ヌル
2420939.72 ヌル 1
2611787.51 ヌル 2
2357570.54 ヌル 3
2796471.48 ヌル 4
2327588.11 ヌル 5
2563701.69 ヌル 6
2442654.38 ヌル 7
2273408.5 ヌル 8
2509228.24 ヌル 9
2716771.77 ヌル 10
2745394.99 ヌル 11
2554721.34 ヌル 12
2526112.36 ヌル 13
2818708.34 ヌル 14
2437768.84 ヌル 15
2246483.68 ヌル 16
2384795.14 ヌル 17
2437849.05 ヌル 18
2470876.07 ヌル 19
2289716.75 ヌル 20




次に、都市、地域、国ごとに支払い額を取得してみましょう。

 SELECT sum(amount), p.city_id, c.state_id, c.country_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id);
      
      





クエリ結果
合計 city_id state_id country_id
2420939.72 1 ヌル ヌル
2611787.51 2 ヌル ヌル
2357570.54 3 ヌル ヌル
2796471.48 4 ヌル ヌル
2327588.11 5 ヌル ヌル
2563701.69 6 ヌル ヌル
2442654.38 7 ヌル ヌル
2273408.5 8 ヌル ヌル
2509228.24 9 ヌル ヌル
2716771.77 10 ヌル ヌル
2745394.99 11 ヌル ヌル
2554721.34 12 ヌル ヌル
2526112.36 13 ヌル ヌル
2818708.34 14 ヌル ヌル
2437768.84 15 ヌル ヌル
2246483.68 16 ヌル ヌル
2384795.14 17 ヌル ヌル
2437849.05 18 ヌル ヌル
2470876.07 19 ヌル ヌル
2289716.75 20 ヌル ヌル
19794121.93 ヌル ヌル 1
30138426.57 ヌル ヌル 2
2611787.51 ヌル 1 ヌル
10045331.82 ヌル 2 ヌル
2442654.38 ヌル 3 ヌル
2273408.5 ヌル 4 ヌル
8016888.1 ヌル 5 ヌル
10029073.22 ヌル 6 ヌル
4822644.19 ヌル 7 ヌル
4760592.82 ヌル 8 ヌル
4930167.96 ヌル ヌル ヌル




奇妙なことに、空のグループ化は行いませんでしたが、すべてのフィールドがNULLの文字列を取得しました。 実際、モスクワとキエフにはstate_idフィールドがなかったため、これが発生しました。そのため、 state_id = NULLでグループ化されたセットを正しくグループ化します 。 これは、次のクエリを実行することで簡単に確認できます。

 SELECT sum(amount) FROM payment WHERE city_id IN (1, 9);
      
      





クエリ結果
合計
4930167.96




はい、私たちの仮定は正しいことが判明し、金額は一致しました。



さて、この奇妙な行がどこから来たのかを理解しましたが、次のクエリで、どの行が合計金額であり、どの行がstate_id = NULLによるグループ化であるかを区別する方法を見つけました

 SELECT sum(amount), p.city_id, c.state_id, c.country_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id, ());
      
      





クエリ結果
合計 city_id state_id country_id
2420939.72 1 ヌル ヌル
2611787.51 2 ヌル ヌル
2357570.54 3 ヌル ヌル
2796471.48 4 ヌル ヌル
2327588.11 5 ヌル ヌル
2563701.69 6 ヌル ヌル
2442654.38 7 ヌル ヌル
2273408.5 8 ヌル ヌル
2509228.24 9 ヌル ヌル
2716771.77 10 ヌル ヌル
2745394.99 11 ヌル ヌル
2554721.34 12 ヌル ヌル
2526112.36 13 ヌル ヌル
2818708.34 14 ヌル ヌル
2437768.84 15 ヌル ヌル
2246483.68 16 ヌル ヌル
2384795.14 17 ヌル ヌル
2437849.05 18 ヌル ヌル
2470876.07 19 ヌル ヌル
2289716.75 20 ヌル ヌル
49932548.5 ヌル ヌル ヌル
19794121.93 ヌル ヌル 1
30138426.57 ヌル ヌル 2
2611787.51 ヌル 1 ヌル
10045331.82 ヌル 2 ヌル
2442654.38 ヌル 3 ヌル
2273408.5 ヌル 4 ヌル
8016888.1 ヌル 5 ヌル
10029073.22 ヌル 6 ヌル
4822644.19 ヌル 7 ヌル
4760592.82 ヌル 8 ヌル
4930167.96 ヌル ヌル ヌル




ですから、全体として、価値はより大きくなるとあなたは言い、あなたは正しいでしょう。 もちろん、このクエリでは、合計の大きい行が合計金額であることを理解できます。 ただし、表に正の値だけでなく負の値も含まれている場合、合計金額を決定することはより困難になります。 さて、または別の集計関数を使用する場合:

 SELECT avg(amount), p.city_id, c.state_id, c.country_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id, ());
      
      





クエリ結果
平均 city_id state_id country_id
4841.87944 1 ヌル ヌル
5141.313996062992126 2 ヌル ヌル
4850.9681893004115226 3 ヌル ヌル
4958.2827659574468085 4 ヌル ヌル
4849.1418958333333333 5 ヌル ヌル
5096.8224453280318091 6 ヌル ヌル
5208.2182942430703625 7 ヌル ヌル
4985.5449561403508772 8 ヌル ヌル
5038.6109236947791165 9 ヌル ヌル
5135.6744234404536862 10 ヌル ヌル
5219.3821102661596958 11 ヌル ヌル
4903.4958541266794626 12 ヌル ヌル
5092.9684677419354839 13 ヌル ヌル
5006.5867495559502664 14 ヌル ヌル
4964.9059877800407332 15 ヌル ヌル
4992.185955555555555556 16 ヌル ヌル
4694.4786220472440945 17 ヌル ヌル
5047.3065217391304348 18 ヌル ヌル
4883.1542885375494071 19 ヌル ヌル
4945.392548596112311 20 ヌル ヌル
4993.25485 ヌル ヌル ヌル
4990.9535879979828543 ヌル ヌル 1
4994.7674129930394432 ヌル ヌル 2
5141.313996062992126 ヌル 1 ヌル
4941.1371470732907034 ヌル 2 ヌル
5208.2182942430703625 ヌル 3 ヌル
4985.5449561403508772 ヌル 4 ヌル
5086.8579314720812183 ヌル 5 ヌル
5014.53661 ヌル 6 ヌル
4866.4421695257315843 ヌル 7 ヌル
4912.8924871001031992 ヌル 8 ヌル
4940.0480561122244489 ヌル ヌル ヌル




表の平均支払額に対応する行と、キエフとモスクワの平均支払額に対応する行はどれですか?

幸いなことに、解決策があります。新しいgrouping()関数を使用すると、特定の列が特定の行のグループに含まれているかどうかを確認できます。 グループ化(column_name)が0を返し、1が関与しない場合、column_nameはグループ化に関与します。

 SELECT avg(amount), p.city_id, c.state_id, c.country_id, grouping(c.state_id) FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id, ());
      
      





クエリ結果
平均 city_id state_id country_id グルーピング
4841.87944 1 ヌル ヌル 1
5141.313996062992126 2 ヌル ヌル 1
4850.9681893004115226 3 ヌル ヌル 1
4958.2827659574468085 4 ヌル ヌル 1
4849.1418958333333333 5 ヌル ヌル 1
5096.8224453280318091 6 ヌル ヌル 1
5208.2182942430703625 7 ヌル ヌル 1
4985.5449561403508772 8 ヌル ヌル 1
5038.6109236947791165 9 ヌル ヌル 1
5135.6744234404536862 10 ヌル ヌル 1
5219.3821102661596958 11 ヌル ヌル 1
4903.4958541266794626 12 ヌル ヌル 1
5092.9684677419354839 13 ヌル ヌル 1
5006.5867495559502664 14 ヌル ヌル 1
4964.9059877800407332 15 ヌル ヌル 1
4992.185955555555555556 16 ヌル ヌル 1
4694.4786220472440945 17 ヌル ヌル 1
5047.3065217391304348 18 ヌル ヌル 1
4883.1542885375494071 19 ヌル ヌル 1
4945.392548596112311 20 ヌル ヌル 1
4993.25485 ヌル ヌル ヌル 1
4990.9535879979828543 ヌル ヌル 1 1
4994.7674129930394432 ヌル ヌル 2 1
5141.313996062992126 ヌル 1 ヌル 0
4941.1371470732907034 ヌル 2 ヌル 0
5208.2182942430703625 ヌル 3 ヌル 0
4985.5449561403508772 ヌル 4 ヌル 0
5086.8579314720812183 ヌル 5 ヌル 0
5014.53661 ヌル 6 ヌル 0
4866.4421695257315843 ヌル 7 ヌル 0
4912.8924871001031992 ヌル 8 ヌル 0
4940.0480561122244489 ヌル ヌル ヌル 0




実際、 グループ化は、リストされている列のビットマスクを返します。

 SELECT avg(amount), p.city_id, c.state_id, c.country_id, grouping(p.city_id, c.state_id, c.country_id) FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id, ());
      
      





クエリ結果
平均 city_id state_id country_id グルーピング
4841.87944 1 ヌル ヌル 3
5141.313996062992126 2 ヌル ヌル 3
4850.9681893004115226 3 ヌル ヌル 3
4958.2827659574468085 4 ヌル ヌル 3
4849.1418958333333333 5 ヌル ヌル 3
5096.8224453280318091 6 ヌル ヌル 3
5208.2182942430703625 7 ヌル ヌル 3
4985.5449561403508772 8 ヌル ヌル 3
5038.6109236947791165 9 ヌル ヌル 3
5135.6744234404536862 10 ヌル ヌル 3
5219.3821102661596958 11 ヌル ヌル 3
4903.4958541266794626 12 ヌル ヌル 3
5092.9684677419354839 13 ヌル ヌル 3
5006.5867495559502664 14 ヌル ヌル 3
4964.9059877800407332 15 ヌル ヌル 3
4992.185955555555555556 16 ヌル ヌル 3
4694.4786220472440945 17 ヌル ヌル 3
5047.3065217391304348 18 ヌル ヌル 3
4883.1542885375494071 19 ヌル ヌル 3
4945.392548596112311 20 ヌル ヌル 3
4993.25485 ヌル ヌル ヌル 7
4990.9535879979828543 ヌル ヌル 1 6
4994.7674129930394432 ヌル ヌル 2 6
5141.313996062992126 ヌル 1 ヌル 5
4941.1371470732907034 ヌル 2 ヌル 5
5208.2182942430703625 ヌル 3 ヌル 5
4985.5449561403508772 ヌル 4 ヌル 5
5086.8579314720812183 ヌル 5 ヌル 5
5014.53661 ヌル 6 ヌル 5
4866.4421695257315843 ヌル 7 ヌル 5
4912.8924871001031992 ヌル 8 ヌル 5
4940.0480561122244489 ヌル ヌル ヌル 5




あまり明確ではないので、タイプビット(3)になります。

 SELECT avg(amount), p.city_id, c.state_id, c.country_id, grouping(p.city_id, c.state_id, c.country_id) :: BIT(3) FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS(p.city_id, c.state_id, c.country_id, ());
      
      





クエリ結果
平均 city_id state_id country_id グルーピング
4841.87944 1 ヌル ヌル 011
5141.313996062992126 2 ヌル ヌル 011
4850.9681893004115226 3 ヌル ヌル 011
4958.2827659574468085 4 ヌル ヌル 011
4849.1418958333333333 5 ヌル ヌル 011
5096.8224453280318091 6 ヌル ヌル 011
5208.2182942430703625 7 ヌル ヌル 011
4985.5449561403508772 8 ヌル ヌル 011
5038.6109236947791165 9 ヌル ヌル 011
5135.6744234404536862 10 ヌル ヌル 011
5219.3821102661596958 11 ヌル ヌル 011
4903.4958541266794626 12 ヌル ヌル 011
5092.9684677419354839 13 ヌル ヌル 011
5006.5867495559502664 14 ヌル ヌル 011
4964.9059877800407332 15 ヌル ヌル 011
4992.185955555555555556 16 ヌル ヌル 011
4694.4786220472440945 17 ヌル ヌル 011
5047.3065217391304348 18 ヌル ヌル 011
4883.1542885375494071 19 ヌル ヌル 011
4945.392548596112311 20 ヌル ヌル 011
4993.25485 ヌル ヌル ヌル 111
4990.9535879979828543 ヌル ヌル 1 110
4994.7674129930394432 ヌル ヌル 2 110
5141.313996062992126 ヌル 1 ヌル 101
4941.1371470732907034 ヌル 2 ヌル 101
5208.2182942430703625 ヌル 3 ヌル 101
4985.5449561403508772 ヌル 4 ヌル 101
5086.8579314720812183 ヌル 5 ヌル 101
5014.53661 ヌル 6 ヌル 101
4866.4421695257315843 ヌル 7 ヌル 101
4912.8924871001031992 ヌル 8 ヌル 101
4940.0480561122244489 ヌル ヌル ヌル 101




GROUPING SETSを使用して、同じクエリで共通のグループ化とグループ化を併用することもできます。

 SELECT avg(amount), c.country_id, p.payment_type_id, p.city_id, c.state_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY c.country_id, p.payment_type_id, GROUPING SETS(p.city_id, c.state_id, ());
      
      





クエリ結果
平均 country_id payment_type_id city_id state_id
5024.1955882352941176 1 1 1 ヌル
4871.1540119760479042 1 1 2 ヌル
4891.0804861111111111 1 1 3 ヌル
5130.3479896907216495 1 1 4 ヌル
4739.4527586206896552 1 1 5 ヌル
4803.7104 1 1 6 ヌル
5028.8194375 1 1 7 ヌル
4903.6742 1 1 8 ヌル
4931.2117088122605364 1 1 ヌル ヌル
4407.8555056179775281 1 2 1 ヌル
5068.5559638554216867 1 2 2 ヌル
4812.6204093567251462 1 2 3 ヌル
4564.1131034482758621 1 2 4 ヌル
4963.2932530120481928 1 2 5 ヌル
5153.3501219512195122 1 2 6 ヌル
5446.8668965517241379 1 2 7 ヌル
5057.8818012422360248 1 2 8 ヌル
4917.934422641509434 1 2 ヌル ヌル
5146.2380921052631579 1 3 1 ヌル
5468.14 1 3 2 ヌル
4855.5371929824561404 1 3 3 ヌル
5137.8994387755102041 1 3 4 ヌル
4831.1288757396449704 1 3 5 ヌル
5353.0667682926829268 1 3 6 ヌル
5172.241280487804878 1 3 7 ヌル
4989.92 1 3 8 ヌル
5121.7272005988023952 1 3 ヌル ヌル
5224.1245625 2 1 9 ヌル
5137.9207142857142857 2 1 10 ヌル
5173.0209625668449198 2 1 11 ヌル
4735.6070652173913043 2 1 12 ヌル
5248.0194285714285714 2 1 13 ヌル
4929.1857978723404255 2 1 14 ヌル
5086.2014102564102564 2 1 15 ヌル
4716.9701273885350318 2 1 16 ヌル
4616.2608383233532934 2 1 17 ヌル
4756.9175641025641026 2 1 18 ヌル
4698.778727272727272727 2 1 19 ヌル
5033.8821276595744681 2 1 20 ヌル
4947.559810379241517 2 1 ヌル ヌル
5195.4805945945945946 2 2 9 ヌル
5213.8818617021276596 2 2 10 ヌル
5332.2921935483870968 2 2 11 ヌル
4946.331030303030303 2 2 12 ヌル
5020.528888888888888889 2 2 13 ヌル
5019.8181914893617021 2 2 14 ヌル
4875.5393452380952381 2 2 15 ヌル
5169.0016551724137931 2 2 16 ヌル
4605.4601807228915663 2 2 17 ヌル
4930.9780838323353293 2 2 18 ヌル
4985.6017441860465116 2 2 19 ヌル
5137.4943046357615894 2 2 20 ヌル
5035.3225511732401398 2 2 ヌル ヌル
4654.930718954248366 2 3 9 ヌル
5048.5046242774566474 2 3 10 ヌル
5171.3846739130434783 2 3 11 ヌル
5042.0059302325581395 2 3 12 ヌル
4997.4288095238095238 2 3 13 ヌル
5071.0994117647058824 2 3 14 ヌル
4941.5018562874251497 2 3 15 ヌル
5110.9062837837837838 2 3 16 ヌル
4853.5610857142857143 2 3 17 ヌル
5451.8535625 2 3 18 ヌル
4958.8998816568047337 2 3 19 ヌル
4702.7937426900584795 2 3 20 ヌル
5001.3644005920078934 2 3 ヌル ヌル
4871.1540119760479042 1 1 ヌル 1
4904.9742705167173252 1 1 ヌル 2
5028.8194375 1 1 ヌル 3
4903.6742 1 1 ヌル 4
5024.1955882352941176 1 1 ヌル ヌル
5068.5559638554216867 1 2 ヌル 1
4868.3998074074074074 1 2 ヌル 2
5446.8668965517241379 1 2 ヌル 3
5057.8818012422360248 1 2 ヌル 4
4407.8555056179775281 1 2 ヌル ヌル
5468.14 1 3 ヌル 1
5045.2698285714285714 1 3 ヌル 2
5172.241280487804878 1 3 ヌル 3
4989.92 1 3 ヌル 4
5146.2380921052631579 1 3 ヌル ヌル
5012.7593692022263451 2 1 ヌル 5
4998.6716863905325444 2 1 ヌル 6
4684.1941176470588235 2 1 ヌル 7
4853.1891176470588235 2 1 ヌル 8
5224.1245625 2 1 ヌル ヌル
5163.1096456692913386 2 2 ヌル 5
5015.9978440366972477 2 2 ヌル 6
4768.7078978978978979 2 2 ヌル 7
5056.6103405572755418 2 2 ヌル 8
5195.4805945945945946 2 2 ヌル ヌル
5089.1325141776937618 2 3 ヌル 5
5029.1172686567164179 2 3 ヌル 6
5139.3127164179104478 2 3 ヌル 7
4830.0935588235294118 2 3 ヌル 8
4654.930718954248366 2 3 ヌル ヌル




GROUPING SETS内の列をグループに結合できます

 SELECT avg(amount), c.country_id, p.payment_type_id, p.city_id, c.state_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY GROUPING SETS((p.payment_type_id, c.country_id), ( c.state_id, p.city_id));
      
      





クエリ結果
平均 country_id payment_type_id city_id state_id
4931.2117088122605364 1 1 ヌル ヌル
4947.559810379241517 2 1 ヌル ヌル
4917.934422641509434 1 2 ヌル ヌル
5035.3225511732401398 2 2 ヌル ヌル
5121.7272005988023952 1 3 ヌル ヌル
5001.3644005920078934 2 3 ヌル ヌル
5141.313996062992126 ヌル ヌル 2 1
4850.9681893004115226 ヌル ヌル 3 2
4958.2827659574468085 ヌル ヌル 4 2
4849.1418958333333333 ヌル ヌル 5 2
5096.8224453280318091 ヌル ヌル 6 2
5208.2182942430703625 ヌル ヌル 7 3
4985.5449561403508772 ヌル ヌル 8 4
5135.6744234404536862 ヌル ヌル 10 5
5219.3821102661596958 ヌル ヌル 11 5
4903.4958541266794626 ヌル ヌル 12 5
5092.9684677419354839 ヌル ヌル 13 6
5006.5867495559502664 ヌル ヌル 14 6
4964.9059877800407332 ヌル ヌル 15 6
4992.185955555555555556 ヌル ヌル 16 6
4694.4786220472440945 ヌル ヌル 17 7
5047.3065217391304348 ヌル ヌル 18 7
4883.1542885375494071 ヌル ヌル 19 8
4945.392548596112311 ヌル ヌル 20 8
4841.87944 ヌル ヌル 1 ヌル
5038.6109236947791165 ヌル ヌル 9 ヌル




それではCUBEに進みましょう。 CUBEは、複数のGROUPING SETSのようなものです。

CUBEは、内部にリストされている列のすべての可能な組み合わせのデータを返します。 つまり、 CUBE( c1、c2、c3 )の場合 (c1、c2、c3は列名です)、次の組み合わせが返されます。

(c1、null、null)

(null、c2、null)

(null、null、c3)

(c1、c2、null)

(c1、null、c3)

(null、c2、c3)

(c1、c2、c3)

(null、null、null)

例:

 SELECT sum(amount), p.payment_type_id, c.country_id, p.city_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY CUBE(p.payment_type_id, c.country_id, p.city_id);
      
      





クエリ結果
合計 payment_type_id country_id city_id
854113.25 1 1 1
813482.72 1 1 2
704315.59 1 1 3
995287.51 1 1 4
687220.65 1 1 5
840649.32 1 1 6
804611.11 1 1 7
735551.13 1 1 8
6435231.28 1 1 ヌル
835859.93 1 2 9
863170.68 1 2 10
967354.92 1 2 11
871351.7 1 2 12
918403.4 1 2 13
926686.93 1 2 14
793447.42 1 2 15
740564.31 1 2 16
770915.56 1 2 17
742079.14 1 2 18
775298.49 1 2 19
709777.38 1 2 20
9914909.86 1 2 ヌル
16350141.14 1 ヌル ヌル
784598.28 2 1 1
841380.29 2 1 2
822958.09 2 1 3
794155.68 2 1 4
823906.68 2 1 5
845149.42 2 1 6
789795.7 2 1 7
814318.97 2 1 8
6516263.11 2 1 ヌル
961163.91 2 2 9
980209.79 2 2 10
826505.29 2 2 11
816144.62 2 2 12
768140.92 2 2 13
943,725.82 2 2 14
819090.61 2 2 15
749505.24 2 2 16
764506.39 2 2 17
823473.34 2 2 18
857523.5 2 2 19
775761.64 2 2 20
10085751.07 2 2 ヌル
16602014.18 2 ヌル ヌル
782228.19 3 1 1
956924.5 3 1 2
830296.86 3 1 3
1007028.29 3 1 4
816460.78 3 1 5
877902.95 3 1 6
848,247.57 3 1 7
723538.4 3 1 8
6842627.54 3 1 ヌル
712204.4 3 2 9
873391.3 3 2 10
951534.78 3 2 11
867225.02 3 2 12
839568.04 3 2 13
948,295.59 3 2 14
825230.81 3 2 15
756414.13 3 2 16
849373.19 3 2 17
872296.57 3 2 18
838054.08 3 2 19
804177.73 3 2 20
10137765.64 3 2 ヌル
16980393.18 3 ヌル ヌル
49932548.5 ヌル ヌル ヌル
854113.25 1 ヌル 1
784598.28 2 ヌル 1
782228.19 3 ヌル 1
2420939.72 ヌル ヌル 1
813482.72 1 ヌル 2
841380.29 2 ヌル 2
956924.5 3 ヌル 2
2611787.51 ヌル ヌル 2
704315.59 1 ヌル 3
822958.09 2 ヌル 3
830296.86 3 ヌル 3
2357570.54 ヌル ヌル 3
995287.51 1 ヌル 4
794155.68 2 ヌル 4
1007028.29 3 ヌル 4
2796471.48 ヌル ヌル 4
687220.65 1 ヌル 5
823906.68 2 ヌル 5
816460.78 3 ヌル 5
2327588.11 ヌル ヌル 5
840649.32 1 ヌル 6
845149.42 2 ヌル 6
877902.95 3 ヌル 6
2563701.69 ヌル ヌル 6
804611.11 1 ヌル 7
789795.7 2 ヌル 7
848,247.57 3 ヌル 7
2442654.38 ヌル ヌル 7
735551.13 1 ヌル 8
814318.97 2 ヌル 8
723538.4 3 ヌル 8
2273408.5 ヌル ヌル 8
835859.93 1 ヌル 9
961163.91 2 ヌル 9
712204.4 3 ヌル 9
2509228.24 ヌル ヌル 9
863170.68 1 ヌル 10
980209.79 2 ヌル 10
873391.3 3 ヌル 10
2716771.77 ヌル ヌル 10
967354.92 1 ヌル 11
826505.29 2 ヌル 11
951534.78 3 ヌル 11
2745394.99 ヌル ヌル 11
871351.7 1 ヌル 12
816144.62 2 ヌル 12
867225.02 3 ヌル 12
2554721.34 ヌル ヌル 12
918403.4 1 ヌル 13
768140.92 2 ヌル 13
839568.04 3 ヌル 13
2526112.36 ヌル ヌル 13
926686.93 1 ヌル 14
943,725.82 2 ヌル 14
948,295.59 3 ヌル 14
2818708.34 ヌル ヌル 14
793447.42 1 ヌル 15
819090.61 2 ヌル 15
825230.81 3 ヌル 15
2437768.84 ヌル ヌル 15
740564.31 1 ヌル 16
749505.24 2 ヌル 16
756414.13 3 ヌル 16
2246483.68 ヌル ヌル 16
770915.56 1 ヌル 17
764506.39 2 ヌル 17
849373.19 3 ヌル 17
2384795.14 ヌル ヌル 17
742079.14 1 ヌル 18
823473.34 2 ヌル 18
872296.57 3 ヌル 18
2437849.05 ヌル ヌル 18
775298.49 1 ヌル 19
857523.5 2 ヌル 19
838054.08 3 ヌル 19
2470876.07 ヌル ヌル 19
709777.38 1 ヌル 20
775761.64 2 ヌル 20
804177.73 3 ヌル 20
2289716.75 ヌル ヌル 20
2420939.72 ヌル 1 1
2611787.51 ヌル 1 2
2357570.54 ヌル 1 3
2796471.48 ヌル 1 4
2327588.11 ヌル 1 5
2563701.69 ヌル 1 6
2442654.38 ヌル 1 7
2273408.5 ヌル 1 8
19794121.93 ヌル 1 ヌル
2509228.24 ヌル 2 9
2716771.77 ヌル 2 10
2745394.99 ヌル 2 11
2554721.34 ヌル 2 12
2526112.36 ヌル 2 13
2818708.34 ヌル 2 14
2437768.84 ヌル 2 15
2246483.68 ヌル 2 16
2384795.14 ヌル 2 17
2437849.05 ヌル 2 18
2470876.07 ヌル 2 19
2289716.75 ヌル 2 20
30138426.57 ヌル 2 ヌル




GROUPING SETSのように、内部でグループ化を行うことができます。

 SELECT sum(amount), p.payment_type_id, c.country_id, p.city_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY CUBE(p.payment_type_id, (c.country_id, p.city_id));
      
      





クエリ結果
合計 payment_type_id country_id city_id
854113.25 1 1 1
813482.72 1 1 2
704315.59 1 1 3
995287.51 1 1 4
687220.65 1 1 5
840649.32 1 1 6
804611.11 1 1 7
735551.13 1 1 8
835859.93 1 2 9
863170.68 1 2 10
967354.92 1 2 11
871351.7 1 2 12
918403.4 1 2 13
926686.93 1 2 14
793447.42 1 2 15
740564.31 1 2 16
770915.56 1 2 17
742079.14 1 2 18
775298.49 1 2 19
709777.38 1 2 20
16350141.14 1 ヌル ヌル
784598.28 2 1 1
841380.29 2 1 2
822958.09 2 1 3
794155.68 2 1 4
823906.68 2 1 5
845149.42 2 1 6
789795.7 2 1 7
814318.97 2 1 8
961163.91 2 2 9
980209.79 2 2 10
826505.29 2 2 11
816144.62 2 2 12
768140.92 2 2 13
943,725.82 2 2 14
819090.61 2 2 15
749505.24 2 2 16
764506.39 2 2 17
823473.34 2 2 18
857523.5 2 2 19
775761.64 2 2 20
16602014.18 2 ヌル ヌル
782228.19 3 1 1
956924.5 3 1 2
830296.86 3 1 3
1007028.29 3 1 4
816460.78 3 1 5
877902.95 3 1 6
848,247.57 3 1 7
723538.4 3 1 8
712204.4 3 2 9
873391.3 3 2 10
951534.78 3 2 11
867225.02 3 2 12
839568.04 3 2 13
948,295.59 3 2 14
825230.81 3 2 15
756414.13 3 2 16
849373.19 3 2 17
872296.57 3 2 18
838054.08 3 2 19
804177.73 3 2 20
16980393.18 3 ヌル ヌル
49932548.5 ヌル ヌル ヌル
2420939.72 ヌル 1 1
2611787.51 ヌル 1 2
2357570.54 ヌル 1 3
2796471.48 ヌル 1 4
2327588.11 ヌル 1 5
2563701.69 ヌル 1 6
2442654.38 ヌル 1 7
2273408.5 ヌル 1 8
2509228.24 ヌル 2 9
2716771.77 ヌル 2 10
2745394.99 ヌル 2 11
2554721.34 ヌル 2 12
2526112.36 ヌル 2 13
2818708.34 ヌル 2 14
2437768.84 ヌル 2 15
2246483.68 ヌル 2 16
2384795.14 ヌル 2 17
2437849.05 ヌル 2 18
2470876.07 ヌル 2 19
2289716.75 ヌル 2 20




ROLLUPCUBEと同じです。複数のGROUPING SETSのようなものですが、 ROLLUPは最後から一度に1列ずつ削除して組み合わせを生成します。 したがって、 ROLLUP( c1、c2、c3、c4は次の組み合わせを返します。

(c1、c2、c3、c4)

(c1、c2、c3、null)

(c1、c2、null、null)

(c1、null、null、null)

(null、null、null、null)

例:

 SELECT sum(amount), p.payment_type_id, c.country_id, p.city_id FROM payment AS p INNER JOIN city AS c ON p.city_id = c.id GROUP BY ROLLUP(p.payment_type_id, c.country_id, p.city_id);
      
      





クエリ結果
合計 payment_type_id country_id city_id
854113.25 1 1 1
813482.72 1 1 2
704315.59 1 1 3
995287.51 1 1 4
687220.65 1 1 5
840649.32 1 1 6
804611.11 1 1 7
735551.13 1 1 8
6435231.28 1 1 ヌル
835859.93 1 2 9
863170.68 1 2 10
967354.92 1 2 11
871351.7 1 2 12
918403.4 1 2 13
926686.93 1 2 14
793447.42 1 2 15
740564.31 1 2 16
770915.56 1 2 17
742079.14 1 2 18
775298.49 1 2 19
709777.38 1 2 20
9914909.86 1 2 ヌル
16350141.14 1 ヌル ヌル
784598.28 2 1 1
841380.29 2 1 2
822958.09 2 1 3
794155.68 2 1 4
823906.68 2 1 5
845149.42 2 1 6
789795.7 2 1 7
814318.97 2 1 8
6516263.11 2 1 ヌル
961163.91 2 2 9
980209.79 2 2 10
826505.29 2 2 11
816144.62 2 2 12
768140.92 2 2 13
943,725.82 2 2 14
819090.61 2 2 15
749505.24 2 2 16
764506.39 2 2 17
823473.34 2 2 18
857523.5 2 2 19
775761.64 2 2 20
10085751.07 2 2 ヌル
16602014.18 2 ヌル ヌル
782228.19 3 1 1
956924.5 3 1 2
830296.86 3 1 3
1007028.29 3 1 4
816460.78 3 1 5
877902.95 3 1 6
848,247.57 3 1 7
723538.4 3 1 8
6842627.54 3 1 ヌル
712204.4 3 2 9
873391.3 3 2 10
951534.78 3 2 11
867225.02 3 2 12
839568.04 3 2 13
948,295.59 3 2 14
825230.81 3 2 15
756414.13 3 2 16
849373.19 3 2 17
872296.57 3 2 18
838054.08 3 2 19
804177.73 3 2 20
10137765.64 3 2 ヌル
16980393.18 3 ヌル ヌル
49932548.5 ヌル ヌル ヌル




結論として、クエリの実行にはUNION ALLの場合に実行される複数のテーブルスキャンの代わりに1つのテーブルスキャンだけが必要なので、記述の利便性に加えて、これらのクエリは潜在的に(まだ自分で測定していません)動作することを言いたいと思います。



ご清聴ありがとうございました!



All Articles