官术网_书友最值得收藏!

  • Mastering PostgreSQL 9.6
  • Hans Jurgen Schonig
  • 575字
  • 2021-07-09 19:57:24

Applying grouping sets

The GROUP BY clause will turn many rows into one row per group. However, if you do reporting in real life, you might also be interested in the overall average. One additional line might be needed.

Here is how this can be achieved:

test=# SELECT region, avg(production) FROM t_oil GROUP BY ROLLUP (region);
region | avg
---------------+-----------------------
Middle East | 1992.6036866359447005
North America | 4541.3623188405797101
| 2607.5139860139860140
(3 rows)

ROLLUP will inject an additional line, which will contain the overall average. If you do reporting, it is highly likely that a summary line will be needed. Instead of running two queries, PostgreSQL can provide the data running just a single query.

Of course, this kind of operation can also be used if you are grouping by more than just one column:

test=# SELECT   region, country, avg(production) FROM t_oil WHERE country IN ('USA', 'Canada', 'Iran', 'Oman') GROUP BY ROLLUP (region, country); 
region | country | avg
---------------+---------+-----------------------
Middle East | Iran | 3631.6956521739130435
Middle East | Oman | 586.4545454545454545
Middle East | | 2142.9111111111111111
North America | Canada | 2123.2173913043478261
North America | USA | 9141.3478260869565217
North America | | 5632.2826086956521739
| | 3906.7692307692307692
(7 rows)

In this example, PostgreSQL will inject three lines into the result set. One line will be injected for Middle East, one for North America. On top of that we will get a line for the overall averages. If you are building a web application the current result is ideal because you can easily build a GUI to drill into the result set by filtering out the null values.

ROLLUP is nice in case you instantly want to display a result. I always used it to display final results to end users. However, if you are doing reporting, you might want to pre-calculate more data to ensure more flexibility. The CUBE keyword is what you might have been looking for:

test=# SELECT   region, country, avg(production) FROM    t_oil WHERE   country IN ('USA', 'Canada', 'Iran', 'Oman') GROUP BY CUBE (region, country); 
region | country | avg
---------------+---------+-----------------------
Middle East | Iran | 3631.6956521739130435
Middle East | Oman | 586.4545454545454545
Middle East | | 2142.9111111111111111
North America | Canada | 2123.2173913043478261
North America | USA | 9141.3478260869565217
North America | | 5632.2826086956521739
| | 3906.7692307692307692
| Canada | 2123.2173913043478261
| Iran | 3631.6956521739130435
| Oman | 586.4545454545454545
| USA | 9141.3478260869565217
(11 rows)

Note that even more rows have been added to the result. CUBE will create the same data as: GROUP BY region, country + GROUP BY region + GROUP BY country + the overall average. So, the whole idea is to extract many results and various levels of aggregation at once. The resulting cube contains all possible combinations of groups.

ROLLUP and CUBE are really just convenience features on top of GROUPING SETS clause. With the GROUPING SETS clause, you can explicitly list the aggregates you want:

test=# SELECT   region, country, avg(production)                                                                                                 FROM    t_oil                                                                                                                                    WHERE   country IN ('USA', 'Canada', 'Iran', 'Oman')                                                                                             GROUP BY GROUPING SETS ( (), region, country); 
region | country | avg
---------------+---------+-----------------------
Middle East | | 2142.9111111111111111
North America | | 5632.2826086956521739
| | 3906.7692307692307692
| Canada | 2123.2173913043478261
| Iran | 3631.6956521739130435
| Oman | 586.4545454545454545
| USA | 9141.3478260869565217
(7 rows)

In this, I went for three grouping sets: the overall average, GROUP BY region and GROUP BY country. If you want regions and countries combined, use (region, country).

主站蜘蛛池模板: 南丰县| 南通市| 黄骅市| 沅陵县| 华阴市| 新蔡县| 丽水市| 铜川市| 南平市| 玛曲县| 察隅县| 郓城县| 乌拉特前旗| 东明县| 新源县| 青阳县| 合山市| 华蓥市| 阿克苏市| 巢湖市| 明光市| 砀山县| 阿尔山市| 宝清县| 定南县| 玉林市| 西畴县| 新平| 杭锦旗| 含山县| 阳高县| 灵璧县| 西城区| 西乌| 兰州市| 西乡县| 丘北县| 修武县| 乌兰察布市| 河东区| 辉县市|