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_idcity_id
19794121.931ヌル
30138426.572ヌル
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_idcity_id
19794121.931ヌル
30138426.572ヌル
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_idcity_id
19794121.931ヌル
30138426.572ヌル
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_idstate_idcountry_id
2420939.721ヌルヌル
2611787.512ヌルヌル
2357570.543ヌルヌル
2796471.484ヌルヌル
2327588.115ヌルヌル
2563701.696ヌルヌル
2442654.387ヌルヌル
2273408.58ヌルヌル
2509228.249ヌルヌル
2716771.7710ヌルヌル
2745394.9911ヌルヌル
2554721.3412ヌルヌル
2526112.3613ヌルヌル
2818708.3414ヌルヌル
2437768.8415ヌルヌル
2246483.6816ヌルヌル
2384795.1417ヌルヌル
2437849.0518ヌルヌル
2470876.0719ヌルヌル
2289716.7520ヌルヌル
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_idstate_idcountry_id
2420939.721ヌルヌル
2611787.512ヌルヌル
2357570.543ヌルヌル
2796471.484ヌルヌル
2327588.115ヌルヌル
2563701.696ヌルヌル
2442654.387ヌルヌル
2273408.58ヌルヌル
2509228.249ヌルヌル
2716771.7710ヌルヌル
2745394.9911ヌルヌル
2554721.3412ヌルヌル
2526112.3613ヌルヌル
2818708.3414ヌルヌル
2437768.8415ヌルヌル
2246483.6816ヌルヌル
2384795.1417ヌルヌル
2437849.0518ヌルヌル
2470876.0719ヌルヌル
2289716.7520ヌルヌル
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_idstate_idcountry_id
4841.879441ヌルヌル
5141.3139960629921262ヌルヌル
4850.96818930041152263ヌルヌル
4958.28276595744680854ヌルヌル
4849.14189583333333335ヌルヌル
5096.82244532803180916ヌルヌル
5208.21829424307036257ヌルヌル
4985.54495614035087728ヌルヌル
5038.61092369477911659ヌルヌル
5135.674423440453686210ヌルヌル
5219.382110266159695811ヌルヌル
4903.495854126679462612ヌルヌル
5092.968467741935483913ヌルヌル
5006.586749555950266414ヌルヌル
4964.905987780040733215ヌルヌル
4992.18595555555555555616ヌルヌル
4694.478622047244094517ヌルヌル
5047.306521739130434818ヌルヌル
4883.154288537549407119ヌルヌル
4945.39254859611231120ヌルヌル
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_idstate_idcountry_idグルーピング
4841.879441ヌルヌル1
5141.3139960629921262ヌルヌル1
4850.96818930041152263ヌルヌル1
4958.28276595744680854ヌルヌル1
4849.14189583333333335ヌルヌル1
5096.82244532803180916ヌルヌル1
5208.21829424307036257ヌルヌル1
4985.54495614035087728ヌルヌル1
5038.61092369477911659ヌルヌル1
5135.674423440453686210ヌルヌル1
5219.382110266159695811ヌルヌル1
4903.495854126679462612ヌルヌル1
5092.968467741935483913ヌルヌル1
5006.586749555950266414ヌルヌル1
4964.905987780040733215ヌルヌル1
4992.18595555555555555616ヌルヌル1
4694.478622047244094517ヌルヌル1
5047.306521739130434818ヌルヌル1
4883.154288537549407119ヌルヌル1
4945.39254859611231120ヌルヌル1
4993.25485ヌルヌルヌル1
4990.9535879979828543ヌルヌル11
4994.7674129930394432ヌルヌル21
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_idstate_idcountry_idグルーピング
4841.879441ヌルヌル3
5141.3139960629921262ヌルヌル3
4850.96818930041152263ヌルヌル3
4958.28276595744680854ヌルヌル3
4849.14189583333333335ヌルヌル3
5096.82244532803180916ヌルヌル3
5208.21829424307036257ヌルヌル3
4985.54495614035087728ヌルヌル3
5038.61092369477911659ヌルヌル3
5135.674423440453686210ヌルヌル3
5219.382110266159695811ヌルヌル3
4903.495854126679462612ヌルヌル3
5092.968467741935483913ヌルヌル3
5006.586749555950266414ヌルヌル3
4964.905987780040733215ヌルヌル3
4992.18595555555555555616ヌルヌル3
4694.478622047244094517ヌルヌル3
5047.306521739130434818ヌルヌル3
4883.154288537549407119ヌルヌル3
4945.39254859611231120ヌルヌル3
4993.25485ヌルヌルヌル7
4990.9535879979828543ヌルヌル16
4994.7674129930394432ヌルヌル26
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_idstate_idcountry_idグルーピング
4841.879441ヌルヌル011
5141.3139960629921262ヌルヌル011
4850.96818930041152263ヌルヌル011
4958.28276595744680854ヌルヌル011
4849.14189583333333335ヌルヌル011
5096.82244532803180916ヌルヌル011
5208.21829424307036257ヌルヌル011
4985.54495614035087728ヌルヌル011
5038.61092369477911659ヌルヌル011
5135.674423440453686210ヌルヌル011
5219.382110266159695811ヌルヌル011
4903.495854126679462612ヌルヌル011
5092.968467741935483913ヌルヌル011
5006.586749555950266414ヌルヌル011
4964.905987780040733215ヌルヌル011
4992.18595555555555555616ヌルヌル011
4694.478622047244094517ヌルヌル011
5047.306521739130434818ヌルヌル011
4883.154288537549407119ヌルヌル011
4945.39254859611231120ヌルヌル011
4993.25485ヌルヌルヌル111
4990.9535879979828543ヌルヌル1110
4994.7674129930394432ヌルヌル2110
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_idpayment_type_idcity_idstate_id
5024.1955882352941176111ヌル
4871.1540119760479042112ヌル
4891.0804861111111111113ヌル
5130.3479896907216495114ヌル
4739.4527586206896552115ヌル
4803.7104116ヌル
5028.8194375117ヌル
4903.6742118ヌル
4931.211708812260536411ヌルヌル
4407.8555056179775281121ヌル
5068.5559638554216867122ヌル
4812.6204093567251462123ヌル
4564.1131034482758621124ヌル
4963.2932530120481928125ヌル
5153.3501219512195122126ヌル
5446.8668965517241379127ヌル
5057.8818012422360248128ヌル
4917.93442264150943412ヌルヌル
5146.2380921052631579131ヌル
5468.14132ヌル
4855.5371929824561404133ヌル
5137.8994387755102041134ヌル
4831.1288757396449704135ヌル
5353.0667682926829268136ヌル
5172.241280487804878137ヌル
4989.92138ヌル
5121.727200598802395213ヌルヌル
5224.1245625219ヌル
5137.92071428571428572110ヌル
5173.02096256684491982111ヌル
4735.60706521739130432112ヌル
5248.01942857142857142113ヌル
4929.18579787234042552114ヌル
5086.20141025641025642115ヌル
4716.97012738853503182116ヌル
4616.26083832335329342117ヌル
4756.91756410256410262118ヌル
4698.7787272727272727272119ヌル
5033.88212765957446812120ヌル
4947.55981037924151721ヌルヌル
5195.4805945945945946229ヌル
5213.88186170212765962210ヌル
5332.29219354838709682211ヌル
4946.3310303030303032212ヌル
5020.5288888888888888892213ヌル
5019.81819148936170212214ヌル
4875.53934523809523812215ヌル
5169.00165517241379312216ヌル
4605.46018072289156632217ヌル
4930.97808383233532932218ヌル
4985.60174418604651162219ヌル
5137.49430463576158942220ヌル
5035.322551173240139822ヌルヌル
4654.930718954248366239ヌル
5048.50462427745664742310ヌル
5171.38467391304347832311ヌル
5042.00593023255813952312ヌル
4997.42880952380952382313ヌル
5071.09941176470588242314ヌル
4941.50185628742514972315ヌル
5110.90628378378378382316ヌル
4853.56108571428571432317ヌル
5451.85356252318ヌル
4958.89988165680473372319ヌル
4702.79374269005847952320ヌル
5001.364400592007893423ヌルヌル
4871.154011976047904211ヌル1
4904.974270516717325211ヌル2
5028.819437511ヌル3
4903.674211ヌル4
5024.195588235294117611ヌルヌル
5068.555963855421686712ヌル1
4868.399807407407407412ヌル2
5446.866896551724137912ヌル3
5057.881801242236024812ヌル4
4407.855505617977528112ヌルヌル
5468.1413ヌル1
5045.269828571428571413ヌル2
5172.24128048780487813ヌル3
4989.9213ヌル4
5146.238092105263157913ヌルヌル
5012.759369202226345121ヌル5
4998.671686390532544421ヌル6
4684.194117647058823521ヌル7
4853.189117647058823521ヌル8
5224.124562521ヌルヌル
5163.109645669291338622ヌル5
5015.997844036697247722ヌル6
4768.707897897897897922ヌル7
5056.610340557275541822ヌル8
5195.480594594594594622ヌルヌル
5089.132514177693761823ヌル5
5029.117268656716417923ヌル6
5139.312716417910447823ヌル7
4830.093558823529411823ヌル8
4654.93071895424836623ヌルヌル


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_idpayment_type_idcity_idstate_id
4931.211708812260536411ヌルヌル
4947.55981037924151721ヌルヌル
4917.93442264150943412ヌルヌル
5035.322551173240139822ヌルヌル
5121.727200598802395213ヌルヌル
5001.364400592007893423ヌルヌル
5141.313996062992126ヌルヌル21
4850.9681893004115226ヌルヌル32
4958.2827659574468085ヌルヌル42
4849.1418958333333333ヌルヌル52
5096.8224453280318091ヌルヌル62
5208.2182942430703625ヌルヌル73
4985.5449561403508772ヌルヌル84
5135.6744234404536862ヌルヌル105
5219.3821102661596958ヌルヌル115
4903.4958541266794626ヌルヌル125
5092.9684677419354839ヌルヌル136
5006.5867495559502664ヌルヌル146
4964.9059877800407332ヌルヌル156
4992.185955555555555556ヌルヌル166
4694.4786220472440945ヌルヌル177
5047.3065217391304348ヌルヌル187
4883.1542885375494071ヌルヌル198
4945.392548596112311ヌルヌル208
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_idcountry_idcity_id
854113.25111
813482.72112
704315.59113
995287.51114
687220.65115
840649.32116
804611.11117
735551.13118
6435231.2811ヌル
835859.93129
863170.681210
967354.921211
871351.71212
918403.41213
926686.931214
793447.421215
740564.311216
770915.561217
742079.141218
775298.491219
709777.381220
9914909.8612ヌル
16350141.141ヌルヌル
784598.28211
841380.29212
822958.09213
794155.68214
823906.68215
845149.42216
789795.7217
814318.97218
6516263.1121ヌル
961163.91229
980209.792210
826505.292211
816144.622212
768140.922213
943,725.822214
819090.612215
749505.242216
764506.392217
823473.342218
857523.52219
775761.642220
10085751.0722ヌル
16602014.182ヌルヌル
782228.19311
956924.5312
830296.86313
1007028.29314
816460.78315
877902.95316
848,247.57317
723538.4318
6842627.5431ヌル
712204.4329
873391.33210
951534.783211
867225.023212
839568.043213
948,295.593214
825230.813215
756414.133216
849373.193217
872296.573218
838054.083219
804177.733220
10137765.6432ヌル
16980393.183ヌルヌル
49932548.5ヌルヌルヌル
854113.251ヌル1
784598.282ヌル1
782228.193ヌル1
2420939.72ヌルヌル1
813482.721ヌル2
841380.292ヌル2
956924.53ヌル2
2611787.51ヌルヌル2
704315.591ヌル3
822958.092ヌル3
830296.863ヌル3
2357570.54ヌルヌル3
995287.511ヌル4
794155.682ヌル4
1007028.293ヌル4
2796471.48ヌルヌル4
687220.651ヌル5
823906.682ヌル5
816460.783ヌル5
2327588.11ヌルヌル5
840649.321ヌル6
845149.422ヌル6
877902.953ヌル6
2563701.69ヌルヌル6
804611.111ヌル7
789795.72ヌル7
848,247.573ヌル7
2442654.38ヌルヌル7
735551.131ヌル8
814318.972ヌル8
723538.43ヌル8
2273408.5ヌルヌル8
835859.931ヌル9
961163.912ヌル9
712204.43ヌル9
2509228.24ヌルヌル9
863170.681ヌル10
980209.792ヌル10
873391.33ヌル10
2716771.77ヌルヌル10
967354.921ヌル11
826505.292ヌル11
951534.783ヌル11
2745394.99ヌルヌル11
871351.71ヌル12
816144.622ヌル12
867225.023ヌル12
2554721.34ヌルヌル12
918403.41ヌル13
768140.922ヌル13
839568.043ヌル13
2526112.36ヌルヌル13
926686.931ヌル14
943,725.822ヌル14
948,295.593ヌル14
2818708.34ヌルヌル14
793447.421ヌル15
819090.612ヌル15
825230.813ヌル15
2437768.84ヌルヌル15
740564.311ヌル16
749505.242ヌル16
756414.133ヌル16
2246483.68ヌルヌル16
770915.561ヌル17
764506.392ヌル17
849373.193ヌル17
2384795.14ヌルヌル17
742079.141ヌル18
823473.342ヌル18
872296.573ヌル18
2437849.05ヌルヌル18
775298.491ヌル19
857523.52ヌル19
838054.083ヌル19
2470876.07ヌルヌル19
709777.381ヌル20
775761.642ヌル20
804177.733ヌル20
2289716.75ヌルヌル20
2420939.72ヌル11
2611787.51ヌル12
2357570.54ヌル13
2796471.48ヌル14
2327588.11ヌル15
2563701.69ヌル16
2442654.38ヌル17
2273408.5ヌル18
19794121.93ヌル1ヌル
2509228.24ヌル29
2716771.77ヌル210
2745394.99ヌル211
2554721.34ヌル212
2526112.36ヌル213
2818708.34ヌル214
2437768.84ヌル215
2246483.68ヌル216
2384795.14ヌル217
2437849.05ヌル218
2470876.07ヌル219
2289716.75ヌル220
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_idcountry_idcity_id
854113.25111
813482.72112
704315.59113
995287.51114
687220.65115
840649.32116
804611.11117
735551.13118
835859.93129
863170.681210
967354.921211
871351.71212
918403.41213
926686.931214
793447.421215
740564.311216
770915.561217
742079.141218
775298.491219
709777.381220
16350141.141ヌルヌル
784598.28211
841380.29212
822958.09213
794155.68214
823906.68215
845149.42216
789795.7217
814318.97218
961163.91229
980209.792210
826505.292211
816144.622212
768140.922213
943,725.822214
819090.612215
749505.242216
764506.392217
823473.342218
857523.52219
775761.642220
16602014.182ヌルヌル
782228.19311
956924.5312
830296.86313
1007028.29314
816460.78315
877902.95316
848,247.57317
723538.4318
712204.4329
873391.33210
951534.783211
867225.023212
839568.043213
948,295.593214
825230.813215
756414.133216
849373.193217
872296.573218
838054.083219
804177.733220
16980393.183ヌルヌル
49932548.5ヌルヌルヌル
2420939.72ヌル11
2611787.51ヌル12
2357570.54ヌル13
2796471.48ヌル14
2327588.11ヌル15
2563701.69ヌル16
2442654.38ヌル17
2273408.5ヌル18
2509228.24ヌル29
2716771.77ヌル210
2745394.99ヌル211
2554721.34ヌル212
2526112.36ヌル213
2818708.34ヌル214
2437768.84ヌル215
2246483.68ヌル216
2384795.14ヌル217
2437849.05ヌル218
2470876.07ヌル219
2289716.75ヌル220


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_idcountry_idcity_id
854113.25111
813482.72112
704315.59113
995287.51114
687220.65115
840649.32116
804611.11117
735551.13118
6435231.2811ヌル
835859.93129
863170.681210
967354.921211
871351.71212
918403.41213
926686.931214
793447.421215
740564.311216
770915.561217
742079.141218
775298.491219
709777.381220
9914909.8612ヌル
16350141.141ヌルヌル
784598.28211
841380.29212
822958.09213
794155.68214
823906.68215
845149.42216
789795.7217
814318.97218
6516263.1121ヌル
961163.91229
980209.792210
826505.292211
816144.622212
768140.922213
943,725.822214
819090.612215
749505.242216
764506.392217
823473.342218
857523.52219
775761.642220
10085751.0722ヌル
16602014.182ヌルヌル
782228.19311
956924.5312
830296.86313
1007028.29314
816460.78315
877902.95316
848,247.57317
723538.4318
6842627.5431ヌル
712204.4329
873391.33210
951534.783211
867225.023212
839568.043213
948,295.593214
825230.813215
756414.133216
849373.193217
872296.573218
838054.083219
804177.733220
10137765.6432ヌル
16980393.183ヌルヌル
49932548.5ヌルヌルヌル


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

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

Source: https://habr.com/ru/post/J269849/


All Articles