We continue to get acquainted with new features in PostgreSQL 9.5.
Part 1. INSERT ... ON CONFLICT DO NOTHING / UPDATE and ROW LEVEL SECURITYPart 2. TABLESAMPLEToday we consider multiple groups in one query. This feature was described in the SQL-99 standard. It is convenient to use it if you need to make several queries to the same table, differing only in the
GROUP BY clause . For this,
GROUPING SETS, ROLLUP, CUBE modifiers are specified as a grouping element after the
GROUP BY keyword.
Let's take a closer look at how this works.
Suppose we have a scheme in which there is data on payments, each payment has a type, a city in which this payment was made and the amount of the payment. The city necessarily has a country and, optionally, a region. Below are the requests to create such a scheme and fill it with data.
Creating a schemaDROP 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);
Suppose we want to get statistics on the amount of payments in each city and in each country. Previously, it was necessary to write a query of the form:
(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)
Query resultsum | country_id | city_id |
---|
19794121.93 | one | Null |
30138426.57 | 2 | Null |
2420939.72 | Null | one |
2611787.51 | Null | 2 |
2357570.54 | Null | 3 |
2796471.48 | Null | four |
2327588.11 | Null | five |
2563701.69 | Null | 6 |
2442654.38 | Null | 7 |
2273408.5 | Null | eight |
2509228.24 | Null | 9 |
2716771.77 | Null | ten |
2745394.99 | Null | eleven |
2554721.34 | Null | 12 |
2526112.36 | Null | 13 |
2818708.34 | Null | 14 |
2437768.84 | Null | 15 |
2246483.68 | Null | sixteen |
2384795.14 | Null | 17 |
2437849.05 | Null | 18 |
2470876.07 | Null | nineteen |
2289716.75 | Null | 20 |
From version 9.5 it is easier to write a similar request like this:
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);
Query resultsum | country_id | city_id |
---|
19794121.93 | one | Null |
30138426.57 | 2 | Null |
2420939.72 | Null | one |
2611787.51 | Null | 2 |
2357570.54 | Null | 3 |
2796471.48 | Null | four |
2327588.11 | Null | five |
2563701.69 | Null | 6 |
2442654.38 | Null | 7 |
2273408.5 | Null | eight |
2509228.24 | Null | 9 |
2716771.77 | Null | ten |
2745394.99 | Null | eleven |
2554721.34 | Null | 12 |
2526112.36 | Null | 13 |
2818708.34 | Null | 14 |
2437768.84 | Null | 15 |
2246483.68 | Null | sixteen |
2384795.14 | Null | 17 |
2437849.05 | Null | 18 |
2470876.07 | Null | nineteen |
2289716.75 | Null | 20 |
As you can see, the
GROUPING SETS as a result of the query returns data as follows: in each row of one of the columns listed in brackets corresponds to the value, while the remaining columns (from the list in brackets) are filled with NULL. Columns not listed in
GROUPING SETS are calculated as usual.
To get the full amount (without grouping), you can use the empty grouping -
() . With empty grouping, all fields participating in
GROUPING SETS are 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, ());
Query resultsum | country_id | city_id |
---|
19794121.93 | one | Null |
30138426.57 | 2 | Null |
49932548.5 | Null | Null |
2420939.72 | Null | one |
2611787.51 | Null | 2 |
2357570.54 | Null | 3 |
2796471.48 | Null | four |
2327588.11 | Null | five |
2563701.69 | Null | 6 |
2442654.38 | Null | 7 |
2273408.5 | Null | eight |
2509228.24 | Null | 9 |
2716771.77 | Null | ten |
2745394.99 | Null | eleven |
2554721.34 | Null | 12 |
2526112.36 | Null | 13 |
2818708.34 | Null | 14 |
2437768.84 | Null | 15 |
2246483.68 | Null | sixteen |
2384795.14 | Null | 17 |
2437849.05 | Null | 18 |
2470876.07 | Null | nineteen |
2289716.75 | Null | 20 |
Now let's try to get the amount of payments in the context of cities, regions and countries:
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);
Query resultsum | city_id | state_id | country_id |
---|
2420939.72 | one | Null | Null |
2611787.51 | 2 | Null | Null |
2357570.54 | 3 | Null | Null |
2796471.48 | four | Null | Null |
2327588.11 | five | Null | Null |
2563701.69 | 6 | Null | Null |
2442654.38 | 7 | Null | Null |
2273408.5 | eight | Null | Null |
2509228.24 | 9 | Null | Null |
2716771.77 | ten | Null | Null |
2745394.99 | eleven | Null | Null |
2554721.34 | 12 | Null | Null |
2526112.36 | 13 | Null | Null |
2818708.34 | 14 | Null | Null |
2437768.84 | 15 | Null | Null |
2246483.68 | sixteen | Null | Null |
2384795.14 | 17 | Null | Null |
2437849.05 | 18 | Null | Null |
2470876.07 | nineteen | Null | Null |
2289716.75 | 20 | Null | Null |
19794121.93 | Null | Null | one |
30138426.57 | Null | Null | 2 |
2611787.51 | Null | one | Null |
10045331.82 | Null | 2 | Null |
2442654.38 | Null | 3 | Null |
2273408.5 | Null | four | Null |
8016888.1 | Null | five | Null |
10029073.22 | Null | 6 | Null |
4822644.19 | Null | 7 | Null |
4760592.82 | Null | eight | Null |
4930167.96 | Null | Null | Null |
Strange, we did not make an empty grouping, but received a string in which all fields are NULL. In fact, this happened because the
state_id field
was not filled in in Moscow and Kiev, therefore
GROUPING SETS rightly did the grouping by
state_id = NULL . This is easily verified by running the following query:
SELECT sum(amount) FROM payment WHERE city_id IN (1, 9);
Yes, our assumption turned out to be true and the amounts coincided.
Well, where did this strange line come from, we figured it out, but how to distinguish in the next query, which of the lines
contains the full amount, and which group is
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, ());
Query resultsum | city_id | state_id | country_id |
---|
2420939.72 | one | Null | Null |
2611787.51 | 2 | Null | Null |
2357570.54 | 3 | Null | Null |
2796471.48 | four | Null | Null |
2327588.11 | five | Null | Null |
2563701.69 | 6 | Null | Null |
2442654.38 | 7 | Null | Null |
2273408.5 | eight | Null | Null |
2509228.24 | 9 | Null | Null |
2716771.77 | ten | Null | Null |
2745394.99 | eleven | Null | Null |
2554721.34 | 12 | Null | Null |
2526112.36 | 13 | Null | Null |
2818708.34 | 14 | Null | Null |
2437768.84 | 15 | Null | Null |
2246483.68 | sixteen | Null | Null |
2384795.14 | 17 | Null | Null |
2437849.05 | 18 | Null | Null |
2470876.07 | nineteen | Null | Null |
2289716.75 | 20 | Null | Null |
49932548.5 | Null | Null | Null |
19794121.93 | Null | Null | one |
30138426.57 | Null | Null | 2 |
2611787.51 | Null | one | Null |
10045331.82 | Null | 2 | Null |
2442654.38 | Null | 3 | Null |
2273408.5 | Null | four | Null |
8016888.1 | Null | five | Null |
10029073.22 | Null | 6 | Null |
4822644.19 | Null | 7 | Null |
4760592.82 | Null | eight | Null |
4930167.96 | Null | Null | Null |
So in fact, the total value will be greater, you say, and you will be right. Of course, in this query, you can understand that the line with the larger amount is the full amount. However, if the table had not only positive values, but also negative ones, it would be more difficult to determine the full amount. Well, or if you use another aggregate function:
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, ());
Query resultavg | city_id | state_id | country_id |
---|
4841.87944 | one | Null | Null |
5141.313996062992126 | 2 | Null | Null |
4850.9681893004115226 | 3 | Null | Null |
4958.2827659574468085 | four | Null | Null |
4849.1418958333333333 | five | Null | Null |
5096.8224453280318091 | 6 | Null | Null |
5208.2182942430703625 | 7 | Null | Null |
4985.5449561403508772 | eight | Null | Null |
5038.6109236947791165 | 9 | Null | Null |
5135.6744234404536862 | ten | Null | Null |
5219.3821102661596958 | eleven | Null | Null |
4903.4958541266794626 | 12 | Null | Null |
5092.9684677419354839 | 13 | Null | Null |
5006.5867495559502664 | 14 | Null | Null |
4964.9059877800407332 | 15 | Null | Null |
4992.1859555555555556 | sixteen | Null | Null |
4694.4786220472440945 | 17 | Null | Null |
5047.3065217391304348 | 18 | Null | Null |
4883.1542885375494071 | nineteen | Null | Null |
4945.392548596112311 | 20 | Null | Null |
4993.25485 | Null | Null | Null |
4990.9535879979828543 | Null | Null | one |
4994.7674129930394432 | Null | Null | 2 |
5141.313996062992126 | Null | one | Null |
4941.1371470732907034 | Null | 2 | Null |
5208.2182942430703625 | Null | 3 | Null |
4985.5449561403508772 | Null | four | Null |
5086.8579314720812183 | Null | five | Null |
5014.53661 | Null | 6 | Null |
4866.4421695257315843 | Null | 7 | Null |
4912.8924871001031992 | Null | eight | Null |
4940.0480561122244489 | Null | Null | Null |
Which line corresponds to the average amount of payment in the table, and which - the average amount in Kiev and Moscow?
Fortunately, there is a solution: the new
grouping () function, with the help of it we can find out whether a particular column is participating in a given row in a grouping. If
grouping (column_name) returns 0, then column_name participates in the grouping, if 1 - does not participate:
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, ());
Query resultavg | city_id | state_id | country_id | grouping |
---|
4841.87944 | one | Null | Null | one |
5141.313996062992126 | 2 | Null | Null | one |
4850.9681893004115226 | 3 | Null | Null | one |
4958.2827659574468085 | four | Null | Null | one |
4849.1418958333333333 | five | Null | Null | one |
5096.8224453280318091 | 6 | Null | Null | one |
5208.2182942430703625 | 7 | Null | Null | one |
4985.5449561403508772 | eight | Null | Null | one |
5038.6109236947791165 | 9 | Null | Null | one |
5135.6744234404536862 | ten | Null | Null | one |
5219.3821102661596958 | eleven | Null | Null | one |
4903.4958541266794626 | 12 | Null | Null | one |
5092.9684677419354839 | 13 | Null | Null | one |
5006.5867495559502664 | 14 | Null | Null | one |
4964.9059877800407332 | 15 | Null | Null | one |
4992.1859555555555556 | sixteen | Null | Null | one |
4694.4786220472440945 | 17 | Null | Null | one |
5047.3065217391304348 | 18 | Null | Null | one |
4883.1542885375494071 | nineteen | Null | Null | one |
4945.392548596112311 | 20 | Null | Null | one |
4993.25485 | Null | Null | Null | one |
4990.9535879979828543 | Null | Null | one | one |
4994.7674129930394432 | Null | Null | 2 | one |
5141.313996062992126 | Null | one | Null | 0 |
4941.1371470732907034 | Null | 2 | Null | 0 |
5208.2182942430703625 | Null | 3 | Null | 0 |
4985.5449561403508772 | Null | four | Null | 0 |
5086.8579314720812183 | Null | five | Null | 0 |
5014.53661 | Null | 6 | Null | 0 |
4866.4421695257315843 | Null | 7 | Null | 0 |
4912.8924871001031992 | Null | eight | Null | 0 |
4940.0480561122244489 | Null | Null | Null | 0 |
In fact,
grouping returns a bitmask for the columns listed in it:
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, ());
Query resultavg | city_id | state_id | country_id | grouping |
---|
4841.87944 | one | Null | Null | 3 |
5141.313996062992126 | 2 | Null | Null | 3 |
4850.9681893004115226 | 3 | Null | Null | 3 |
4958.2827659574468085 | four | Null | Null | 3 |
4849.1418958333333333 | five | Null | Null | 3 |
5096.8224453280318091 | 6 | Null | Null | 3 |
5208.2182942430703625 | 7 | Null | Null | 3 |
4985.5449561403508772 | eight | Null | Null | 3 |
5038.6109236947791165 | 9 | Null | Null | 3 |
5135.6744234404536862 | ten | Null | Null | 3 |
5219.3821102661596958 | eleven | Null | Null | 3 |
4903.4958541266794626 | 12 | Null | Null | 3 |
5092.9684677419354839 | 13 | Null | Null | 3 |
5006.5867495559502664 | 14 | Null | Null | 3 |
4964.9059877800407332 | 15 | Null | Null | 3 |
4992.1859555555555556 | sixteen | Null | Null | 3 |
4694.4786220472440945 | 17 | Null | Null | 3 |
5047.3065217391304348 | 18 | Null | Null | 3 |
4883.1542885375494071 | nineteen | Null | Null | 3 |
4945.392548596112311 | 20 | Null | Null | 3 |
4993.25485 | Null | Null | Null | 7 |
4990.9535879979828543 | Null | Null | one | 6 |
4994.7674129930394432 | Null | Null | 2 | 6 |
5141.313996062992126 | Null | one | Null | five |
4941.1371470732907034 | Null | 2 | Null | five |
5208.2182942430703625 | Null | 3 | Null | five |
4985.5449561403508772 | Null | four | Null | five |
5086.8579314720812183 | Null | five | Null | five |
5014.53661 | Null | 6 | Null | five |
4866.4421695257315843 | Null | 7 | Null | five |
4912.8924871001031992 | Null | eight | Null | five |
4940.0480561122244489 | Null | Null | Null | five |
So it is not very clear, we will bring the result to the
bit (3) type :
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, ());
Query resultavg | city_id | state_id | country_id | grouping |
---|
4841.87944 | one | Null | Null | 011 |
5141.313996062992126 | 2 | Null | Null | 011 |
4850.9681893004115226 | 3 | Null | Null | 011 |
4958.2827659574468085 | four | Null | Null | 011 |
4849.1418958333333333 | five | Null | Null | 011 |
5096.8224453280318091 | 6 | Null | Null | 011 |
5208.2182942430703625 | 7 | Null | Null | 011 |
4985.5449561403508772 | eight | Null | Null | 011 |
5038.6109236947791165 | 9 | Null | Null | 011 |
5135.6744234404536862 | ten | Null | Null | 011 |
5219.3821102661596958 | eleven | Null | Null | 011 |
4903.4958541266794626 | 12 | Null | Null | 011 |
5092.9684677419354839 | 13 | Null | Null | 011 |
5006.5867495559502664 | 14 | Null | Null | 011 |
4964.9059877800407332 | 15 | Null | Null | 011 |
4992.1859555555555556 | sixteen | Null | Null | 011 |
4694.4786220472440945 | 17 | Null | Null | 011 |
5047.3065217391304348 | 18 | Null | Null | 011 |
4883.1542885375494071 | nineteen | Null | Null | 011 |
4945.392548596112311 | 20 | Null | Null | 011 |
4993.25485 | Null | Null | Null | 111 |
4990.9535879979828543 | Null | Null | one | 110 |
4994.7674129930394432 | Null | Null | 2 | 110 |
5141.313996062992126 | Null | one | Null | 101 |
4941.1371470732907034 | Null | 2 | Null | 101 |
5208.2182942430703625 | Null | 3 | Null | 101 |
4985.5449561403508772 | Null | four | Null | 101 |
5086.8579314720812183 | Null | five | Null | 101 |
5014.53661 | Null | 6 | Null | 101 |
4866.4421695257315843 | Null | 7 | Null | 101 |
4912.8924871001031992 | Null | eight | Null | 101 |
4940.0480561122244489 | Null | Null | Null | 101 |
You can also use common grouping and grouping together in a single query using
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, ());
Query resultavg | country_id | payment_type_id | city_id | state_id |
---|
5024.1955882352941176 | one | one | one | Null |
4871.1540119760479042 | one | one | 2 | Null |
4891.0804861111111111 | one | one | 3 | Null |
5130.3479896907216495 | one | one | four | Null |
4739.4527586206896552 | one | one | five | Null |
4803.7104 | one | one | 6 | Null |
5028.8194375 | one | one | 7 | Null |
4903.6742 | one | one | eight | Null |
4931.2117088122605364 | one | one | Null | Null |
4407.8555056179775281 | one | 2 | one | Null |
5068.5559638554216867 | one | 2 | 2 | Null |
4812.6204093567251462 | one | 2 | 3 | Null |
4564.1131034482758621 | one | 2 | four | Null |
4963.2932530120481928 | one | 2 | five | Null |
5153.3501219512195122 | one | 2 | 6 | Null |
5446.8668965517241379 | one | 2 | 7 | Null |
5057.8818012422360248 | one | 2 | eight | Null |
4917.934422641509434 | one | 2 | Null | Null |
5146.2380921052631579 | one | 3 | one | Null |
5468.14 | one | 3 | 2 | Null |
4855.5371929824561404 | one | 3 | 3 | Null |
5137.8994387755102041 | one | 3 | four | Null |
4831.1288757396449704 | one | 3 | five | Null |
5353.0667682926829268 | one | 3 | 6 | Null |
5172.241280487804878 | one | 3 | 7 | Null |
4989.92 | one | 3 | eight | Null |
5121.7272005988023952 | one | 3 | Null | Null |
5224.1245625 | 2 | one | 9 | Null |
5137.9207142857142857 | 2 | one | ten | Null |
5173.0209625668449198 | 2 | one | eleven | Null |
4735.6070652173913043 | 2 | one | 12 | Null |
5248.0194285714285714 | 2 | one | 13 | Null |
4929.1857978723404255 | 2 | one | 14 | Null |
5086.2014 102564102564 | 2 | one | 15 | Null |
4716.9701273885350318 | 2 | one | sixteen | Null |
4616.2608383233532934 | 2 | one | 17 | Null |
4756.9175641025641026 | 2 | one | 18 | Null |
4698.7787272727272727 | 2 | one | nineteen | Null |
5033.8821276595744681 | 2 | one | 20 | Null |
4947.559810379241517 | 2 | one | Null | Null |
5195.4805945945945946 | 2 | 2 | 9 | Null |
5213.8818617021276596 | 2 | 2 | ten | Null |
5332.2921935483870968 | 2 | 2 | eleven | Null |
4946.331030303030303 | 2 | 2 | 12 | Null |
5020.5288888888888889 | 2 | 2 | 13 | Null |
5019.8181914893617021 | 2 | 2 | 14 | Null |
4875.5393452380952381 | 2 | 2 | 15 | Null |
5169.0016551724137931 | 2 | 2 | sixteen | Null |
4605.4601807228915663 | 2 | 2 | 17 | Null |
4930.9780838323353293 | 2 | 2 | 18 | Null |
4985.6017441860465116 | 2 | 2 | nineteen | Null |
5137.4943046357615894 | 2 | 2 | 20 | Null |
5035.3225511732401398 | 2 | 2 | Null | Null |
4654.930718954248366 | 2 | 3 | 9 | Null |
5048.5046242774566474 | 2 | 3 | ten | Null |
5171.3846739130434783 | 2 | 3 | eleven | Null |
5042.0059302325581395 | 2 | 3 | 12 | Null |
4997.4288095238095238 | 2 | 3 | 13 | Null |
5071.0994117647058824 | 2 | 3 | 14 | Null |
4941.5018562874251497 | 2 | 3 | 15 | Null |
5110.9062837837837838 | 2 | 3 | sixteen | Null |
4853.5610857142857143 | 2 | 3 | 17 | Null |
5451.8535625 | 2 | 3 | 18 | Null |
4958.8998816568047337 | 2 | 3 | nineteen | Null |
4702.7937426900584795 | 2 | 3 | 20 | Null |
5001.3644005920078934 | 2 | 3 | Null | Null |
4871.1540119760479042 | one | one | Null | one |
4904.9742705167173252 | one | one | Null | 2 |
5028.8194375 | one | one | Null | 3 |
4903.6742 | one | one | Null | four |
5024.1955882352941176 | one | one | Null | Null |
5068.5559638554216867 | one | 2 | Null | one |
4868.3998074074074074 | one | 2 | Null | 2 |
5446.8668965517241379 | one | 2 | Null | 3 |
5057.8818012422360248 | one | 2 | Null | four |
4407.8555056179775281 | one | 2 | Null | Null |
5468.14 | one | 3 | Null | one |
5045.2698285714285714 | one | 3 | Null | 2 |
5172.241280487804878 | one | 3 | Null | 3 |
4989.92 | one | 3 | Null | four |
5146.2380921052631579 | one | 3 | Null | Null |
5012.7593692022263451 | 2 | one | Null | five |
4998.6716863905325444 | 2 | one | Null | 6 |
4684.1941176470588235 | 2 | one | Null | 7 |
4853.1891176470588235 | 2 | one | Null | eight |
5224.1245625 | 2 | one | Null | Null |
5163.1096456692913386 | 2 | 2 | Null | five |
5015.9978440366972477 | 2 | 2 | Null | 6 |
4768.7078978978978979 | 2 | 2 | Null | 7 |
5056.6103405572755418 | 2 | 2 | Null | eight |
5195.4805945945945946 | 2 | 2 | Null | Null |
5089.1325141776937618 | 2 | 3 | Null | five |
5029.1172686567164179 | 2 | 3 | Null | 6 |
5139.3127164179104478 | 2 | 3 | Null | 7 |
4830.0935588235294118 | 2 | 3 | Null | eight |
4654.930718954248366 | 2 | 3 | Null | Null |
You can combine the columns inside the
GROUPING SETS into groups
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));
Query resultavg | country_id | payment_type_id | city_id | state_id |
---|
4931.2117088122605364 | one | one | Null | Null |
4947.559810379241517 | 2 | one | Null | Null |
4917.934422641509434 | one | 2 | Null | Null |
5035.3225511732401398 | 2 | 2 | Null | Null |
5121.7272005988023952 | one | 3 | Null | Null |
5001.3644005920078934 | 2 | 3 | Null | Null |
5141.313996062992126 | Null | Null | 2 | one |
4850.9681893004115226 | Null | Null | 3 | 2 |
4958.2827659574468085 | Null | Null | four | 2 |
4849.1418958333333333 | Null | Null | five | 2 |
5096.8224453280318091 | Null | Null | 6 | 2 |
5208.2182942430703625 | Null | Null | 7 | 3 |
4985.5449561403508772 | Null | Null | eight | four |
5135.6744234404536862 | Null | Null | ten | five |
5219.3821102661596958 | Null | Null | eleven | five |
4903.4958541266794626 | Null | Null | 12 | five |
5092.9684677419354839 | Null | Null | 13 | 6 |
5006.5867495559502664 | Null | Null | 14 | 6 |
4964.9059877800407332 | Null | Null | 15 | 6 |
4992.1859555555555556 | Null | Null | sixteen | 6 |
4694.4786220472440945 | Null | Null | 17 | 7 |
5047.3065217391304348 | Null | Null | 18 | 7 |
4883.1542885375494071 | Null | Null | nineteen | eight |
4945.392548596112311 | Null | Null | 20 | eight |
4841.87944 | Null | Null | one | Null |
5038.6109236947791165 | Null | Null | 9 | Null |
We now turn to
CUBE .
CUBE is something like a multiple
GROUPING SETS .
CUBE returns data for all possible combinations of columns listed inside. That is, for the case of
CUBE ( c1, c2, c3 ) (where c1, c2, c3 are the column names), the following combinations will be returned:
(c1, null, null)
(null, c2, null)
(null, null, c3)
(c1, c2, null)
(c1, null, c3)
(null, c2, c3)
(c1, c2, c3)
(null, null, null)Example:
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);
Query resultsum | payment_type_id | country_id | city_id |
---|
854113.25 | one | one | one |
813482.72 | one | one | 2 |
704315.59 | one | one | 3 |
995287.51 | one | one | four |
687220.65 | one | one | five |
840649.32 | one | one | 6 |
804611.11 | one | one | 7 |
735551.13 | one | one | eight |
6435231.28 | one | one | Null |
835859.93 | one | 2 | 9 |
863170.68 | one | 2 | ten |
967354.92 | one | 2 | eleven |
871351.7 | one | 2 | 12 |
918403.4 | one | 2 | 13 |
926686.93 | one | 2 | 14 |
793447.42 | one | 2 | 15 |
740564.31 | one | 2 | sixteen |
770915.56 | one | 2 | 17 |
742079.14 | one | 2 | 18 |
775298.49 | one | 2 | nineteen |
709777.38 | one | 2 | 20 |
9914909.86 | one | 2 | Null |
16350141.14 | one | Null | Null |
784598.28 | 2 | one | one |
841380.29 | 2 | one | 2 |
822958.09 | 2 | one | 3 |
794155.68 | 2 | one | four |
823906.68 | 2 | one | five |
845149.42 | 2 | one | 6 |
789795.7 | 2 | one | 7 |
814318.97 | 2 | one | eight |
6516263.11 | 2 | one | Null |
961163.91 | 2 | 2 | 9 |
980209.79 | 2 | 2 | ten |
826505.29 | 2 | 2 | eleven |
816144.62 | 2 | 2 | 12 |
768140.92 | 2 | 2 | 13 |
943725.82 | 2 | 2 | 14 |
819090.61 | 2 | 2 | 15 |
749505.24 | 2 | 2 | sixteen |
764506.39 | 2 | 2 | 17 |
823473.34 | 2 | 2 | 18 |
857523.5 | 2 | 2 | nineteen |
775761.64 | 2 | 2 | 20 |
10085751.07 | 2 | 2 | Null |
16602014.18 | 2 | Null | Null |
782228.19 | 3 | one | one |
956924.5 | 3 | one | 2 |
830296.86 | 3 | one | 3 |
1007028.29 | 3 | one | four |
816460.78 | 3 | one | five |
877902.95 | 3 | one | 6 |
848247.57 | 3 | one | 7 |
723538.4 | 3 | one | eight |
6842627.54 | 3 | one | Null |
712204.4 | 3 | 2 | 9 |
873391.3 | 3 | 2 | ten |
951534.78 | 3 | 2 | eleven |
867225.02 | 3 | 2 | 12 |
839568.04 | 3 | 2 | 13 |
948295.59 | 3 | 2 | 14 |
825230.81 | 3 | 2 | 15 |
756414.13 | 3 | 2 | sixteen |
849373.19 | 3 | 2 | 17 |
872296.57 | 3 | 2 | 18 |
838054.08 | 3 | 2 | nineteen |
804177.73 | 3 | 2 | 20 |
10137765.64 | 3 | 2 | Null |
16980393.18 | 3 | Null | Null |
49932548.5 | Null | Null | Null |
854113.25 | one | Null | one |
784598.28 | 2 | Null | one |
782228.19 | 3 | Null | one |
2420939.72 | Null | Null | one |
813482.72 | one | Null | 2 |
841380.29 | 2 | Null | 2 |
956924.5 | 3 | Null | 2 |
2611787.51 | Null | Null | 2 |
704315.59 | one | Null | 3 |
822958.09 | 2 | Null | 3 |
830296.86 | 3 | Null | 3 |
2357570.54 | Null | Null | 3 |
995287.51 | one | Null | four |
794155.68 | 2 | Null | four |
1007028.29 | 3 | Null | four |
2796471.48 | Null | Null | four |
687220.65 | one | Null | five |
823906.68 | 2 | Null | five |
816460.78 | 3 | Null | five |
2327588.11 | Null | Null | five |
840649.32 | one | Null | 6 |
845149.42 | 2 | Null | 6 |
877902.95 | 3 | Null | 6 |
2563701.69 | Null | Null | 6 |
804611.11 | one | Null | 7 |
789795.7 | 2 | Null | 7 |
848247.57 | 3 | Null | 7 |
2442654.38 | Null | Null | 7 |
735551.13 | one | Null | eight |
814318.97 | 2 | Null | eight |
723538.4 | 3 | Null | eight |
2273408.5 | Null | Null | eight |
835859.93 | one | Null | 9 |
961163.91 | 2 | Null | 9 |
712204.4 | 3 | Null | 9 |
2509228.24 | Null | Null | 9 |
863170.68 | one | Null | ten |
980209.79 | 2 | Null | ten |
873391.3 | 3 | Null | ten |
2716771.77 | Null | Null | ten |
967354.92 | one | Null | eleven |
826505.29 | 2 | Null | eleven |
951534.78 | 3 | Null | eleven |
2745394.99 | Null | Null | eleven |
871351.7 | one | Null | 12 |
816144.62 | 2 | Null | 12 |
867225.02 | 3 | Null | 12 |
2554721.34 | Null | Null | 12 |
918403.4 | one | Null | 13 |
768140.92 | 2 | Null | 13 |
839568.04 | 3 | Null | 13 |
2526112.36 | Null | Null | 13 |
926686.93 | one | Null | 14 |
943725.82 | 2 | Null | 14 |
948295.59 | 3 | Null | 14 |
2818708.34 | Null | Null | 14 |
793447.42 | one | Null | 15 |
819090.61 | 2 | Null | 15 |
825230.81 | 3 | Null | 15 |
2437768.84 | Null | Null | 15 |
740564.31 | one | Null | sixteen |
749505.24 | 2 | Null | sixteen |
756414.13 | 3 | Null | sixteen |
2246483.68 | Null | Null | sixteen |
770915.56 | one | Null | 17 |
764506.39 | 2 | Null | 17 |
849373.19 | 3 | Null | 17 |
2384795.14 | Null | Null | 17 |
742079.14 | one | Null | 18 |
823473.34 | 2 | Null | 18 |
872296.57 | 3 | Null | 18 |
2437849.05 | Null | Null | 18 |
775298.49 | one | Null | nineteen |
857523.5 | 2 | Null | nineteen |
838054.08 | 3 | Null | nineteen |
2470876.07 | Null | Null | nineteen |
709777.38 | one | Null | 20 |
775761.64 | 2 | Null | 20 |
804177.73 | 3 | Null | 20 |
2289716.75 | Null | Null | 20 |
2420939.72 | Null | one | one |
2611787.51 | Null | one | 2 |
2357570.54 | Null | one | 3 |
2796471.48 | Null | one | four |
2327588.11 | Null | one | five |
2563701.69 | Null | one | 6 |
2442654.38 | Null | one | 7 |
2273408.5 | Null | one | eight |
19794121.93 | Null | one | Null |
2509228.24 | Null | 2 | 9 |
2716771.77 | Null | 2 | ten |
2745394.99 | Null | 2 | eleven |
2554721.34 | Null | 2 | 12 |
2526112.36 | Null | 2 | 13 |
2818708.34 | Null | 2 | 14 |
2437768.84 | Null | 2 | 15 |
2246483.68 | Null | 2 | sixteen |
2384795.14 | Null | 2 | 17 |
2437849.05 | Null | 2 | 18 |
2470876.07 | Null | 2 | nineteen |
2289716.75 | Null | 2 | 20 |
30138426.57 | Null | 2 | Null |
As in
GROUPING SETS, you can do grouping inside:
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));
Query resultsum | payment_type_id | country_id | city_id |
---|
854113.25 | one | one | one |
813482.72 | one | one | 2 |
704315.59 | one | one | 3 |
995287.51 | one | one | four |
687220.65 | one | one | five |
840649.32 | one | one | 6 |
804611.11 | one | one | 7 |
735551.13 | one | one | eight |
835859.93 | one | 2 | 9 |
863170.68 | one | 2 | ten |
967354.92 | one | 2 | eleven |
871351.7 | one | 2 | 12 |
918403.4 | one | 2 | 13 |
926686.93 | one | 2 | 14 |
793447.42 | one | 2 | 15 |
740564.31 | one | 2 | sixteen |
770915.56 | one | 2 | 17 |
742079.14 | one | 2 | 18 |
775298.49 | one | 2 | nineteen |
709777.38 | one | 2 | 20 |
16350141.14 | one | Null | Null |
784598.28 | 2 | one | one |
841380.29 | 2 | one | 2 |
822958.09 | 2 | one | 3 |
794155.68 | 2 | one | four |
823906.68 | 2 | one | five |
845149.42 | 2 | one | 6 |
789795.7 | 2 | one | 7 |
814318.97 | 2 | one | eight |
961163.91 | 2 | 2 | 9 |
980209.79 | 2 | 2 | ten |
826505.29 | 2 | 2 | eleven |
816144.62 | 2 | 2 | 12 |
768140.92 | 2 | 2 | 13 |
943725.82 | 2 | 2 | 14 |
819090.61 | 2 | 2 | 15 |
749505.24 | 2 | 2 | sixteen |
764506.39 | 2 | 2 | 17 |
823473.34 | 2 | 2 | 18 |
857523.5 | 2 | 2 | nineteen |
775761.64 | 2 | 2 | 20 |
16602014.18 | 2 | Null | Null |
782228.19 | 3 | one | one |
956924.5 | 3 | one | 2 |
830296.86 | 3 | one | 3 |
1007028.29 | 3 | one | four |
816460.78 | 3 | one | five |
877902.95 | 3 | one | 6 |
848247.57 | 3 | one | 7 |
723538.4 | 3 | one | eight |
712204.4 | 3 | 2 | 9 |
873391.3 | 3 | 2 | ten |
951534.78 | 3 | 2 | eleven |
867225.02 | 3 | 2 | 12 |
839568.04 | 3 | 2 | 13 |
948295.59 | 3 | 2 | 14 |
825230.81 | 3 | 2 | 15 |
756414.13 | 3 | 2 | sixteen |
849373.19 | 3 | 2 | 17 |
872296.57 | 3 | 2 | 18 |
838054.08 | 3 | 2 | nineteen |
804177.73 | 3 | 2 | 20 |
16980393.18 | 3 | Null | Null |
49932548.5 | Null | Null | Null |
2420939.72 | Null | one | one |
2611787.51 | Null | one | 2 |
2357570.54 | Null | one | 3 |
2796471.48 | Null | one | four |
2327588.11 | Null | one | five |
2563701.69 | Null | one | 6 |
2442654.38 | Null | one | 7 |
2273408.5 | Null | one | eight |
2509228.24 | Null | 2 | 9 |
2716771.77 | Null | 2 | ten |
2745394.99 | Null | 2 | eleven |
2554721.34 | Null | 2 | 12 |
2526112.36 | Null | 2 | 13 |
2818708.34 | Null | 2 | 14 |
2437768.84 | Null | 2 | 15 |
2246483.68 | Null | 2 | sixteen |
2384795.14 | Null | 2 | 17 |
2437849.05 | Null | 2 | 18 |
2470876.07 | Null | 2 | nineteen |
2289716.75 | Null | 2 | 20 |
ROLLUP is the same as
CUBE - something like multiple
GROUPING SETS , with the difference that
ROLLUP generates combinations, removing columns one by one from the end. Thus,
ROLLUP ( c1, c2, c3, c4 ) will return the following combinations:
(c1, c2, c3, c4)
(c1, c2, c3, null)
(c1, c2, null, null)
(c1, null, null, null)
(null, null, null, null)Example:
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);
Query resultsum | payment_type_id | country_id | city_id |
---|
854113.25 | one | one | one |
813482.72 | one | one | 2 |
704315.59 | one | one | 3 |
995287.51 | one | one | four |
687220.65 | one | one | five |
840649.32 | one | one | 6 |
804611.11 | one | one | 7 |
735551.13 | one | one | eight |
6435231.28 | one | one | Null |
835859.93 | one | 2 | 9 |
863170.68 | one | 2 | ten |
967354.92 | one | 2 | eleven |
871351.7 | one | 2 | 12 |
918403.4 | one | 2 | 13 |
926686.93 | one | 2 | 14 |
793447.42 | one | 2 | 15 |
740564.31 | one | 2 | sixteen |
770915.56 | one | 2 | 17 |
742079.14 | one | 2 | 18 |
775298.49 | one | 2 | nineteen |
709777.38 | one | 2 | 20 |
9914909.86 | one | 2 | Null |
16350141.14 | one | Null | Null |
784598.28 | 2 | one | one |
841380.29 | 2 | one | 2 |
822958.09 | 2 | one | 3 |
794155.68 | 2 | one | four |
823906.68 | 2 | one | five |
845149.42 | 2 | one | 6 |
789795.7 | 2 | one | 7 |
814318.97 | 2 | one | eight |
6516263.11 | 2 | one | Null |
961163.91 | 2 | 2 | 9 |
980209.79 | 2 | 2 | ten |
826505.29 | 2 | 2 | eleven |
816144.62 | 2 | 2 | 12 |
768140.92 | 2 | 2 | 13 |
943725.82 | 2 | 2 | 14 |
819090.61 | 2 | 2 | 15 |
749505.24 | 2 | 2 | sixteen |
764506.39 | 2 | 2 | 17 |
823473.34 | 2 | 2 | 18 |
857523.5 | 2 | 2 | nineteen |
775761.64 | 2 | 2 | 20 |
10085751.07 | 2 | 2 | Null |
16602014.18 | 2 | Null | Null |
782228.19 | 3 | one | one |
956924.5 | 3 | one | 2 |
830296.86 | 3 | one | 3 |
1007028.29 | 3 | one | four |
816460.78 | 3 | one | five |
877902.95 | 3 | one | 6 |
848247.57 | 3 | one | 7 |
723538.4 | 3 | one | eight |
6842627.54 | 3 | one | Null |
712204.4 | 3 | 2 | 9 |
873391.3 | 3 | 2 | ten |
951534.78 | 3 | 2 | eleven |
867225.02 | 3 | 2 | 12 |
839568.04 | 3 | 2 | 13 |
948295.59 | 3 | 2 | 14 |
825230.81 | 3 | 2 | 15 |
756414.13 | 3 | 2 | sixteen |
849373.19 | 3 | 2 | 17 |
872296.57 | 3 | 2 | 18 |
838054.08 | 3 | 2 | nineteen |
804177.73 | 3 | 2 | 20 |
10137765.64 | 3 | 2 | Null |
16980393.18 | 3 | Null | Null |
49932548.5 | Null | Null | Null |
In conclusion, I want to say that, besides the convenience of writing, these queries are potentially (not yet merit), work faster, since to execute a query you need only one table scan instead of several that are performed in the case of
UNION ALL .
')
Thanks for attention!