mirror of
https://github.com/postgres/postgres.git
synced 2025-12-21 05:21:08 +03:00
Add GROUP BY ALL.
GROUP BY ALL is a form of GROUP BY that adds any TargetExpr that does not contain an aggregate or window function into the groupClause of the query, making it exactly equivalent to specifying those same expressions in an explicit GROUP BY list. This feature is useful for certain kinds of data exploration. It's already present in some other DBMSes, and the SQL committee recently accepted it into the standard, so we can be reasonably confident in the syntax being stable. We do have to invent part of the semantics, as the standard doesn't allow for expressions in GROUP BY, so they haven't specified what to do with window functions. We assume that those should be treated like aggregates, i.e., left out of the constructed GROUP BY list. In passing, wordsmith some existing documentation about GROUP BY, and update some neglected synopsis entries in select_into.sgml. Author: David Christensen <david@pgguru.net> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/CAHM0NXjz0kDwtzoe-fnHAqPB1qA8_VJN0XAmCgUZ+iPnvP5LbA@mail.gmail.com
This commit is contained in:
@@ -1557,6 +1557,129 @@ drop table t2;
|
||||
drop table t3;
|
||||
drop table p_t1;
|
||||
--
|
||||
-- Test GROUP BY ALL
|
||||
--
|
||||
-- We don't care about the data here, just the proper transformation of the
|
||||
-- GROUP BY clause, so test some queries and verify the EXPLAIN plans.
|
||||
--
|
||||
CREATE TEMP TABLE t1 (
|
||||
a int,
|
||||
b int,
|
||||
c int
|
||||
);
|
||||
-- basic example
|
||||
EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: b
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- multiple columns, non-consecutive order
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: a, b
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- multi columns, no aggregate
|
||||
EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: (a + b)
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- check we detect a non-top-level aggregate
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: a
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- including grouped column is okay
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: a
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- including non-grouped column, not so much
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL;
|
||||
ERROR: column "t1.c" must appear in the GROUP BY clause or be used in an aggregate function
|
||||
LINE 1: EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY AL...
|
||||
^
|
||||
-- all aggregates, should reduce to GROUP BY ()
|
||||
EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
Aggregate
|
||||
Group Key: ()
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- likewise with empty target list
|
||||
EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
-----------------------
|
||||
Result
|
||||
Replaces: Aggregate
|
||||
(2 rows)
|
||||
|
||||
-- window functions are not to be included in GROUP BY, either
|
||||
EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------------------
|
||||
WindowAgg
|
||||
Window: w1 AS (PARTITION BY a)
|
||||
-> Sort
|
||||
Sort Key: a
|
||||
-> HashAggregate
|
||||
Group Key: a
|
||||
-> Seq Scan on t1
|
||||
(7 rows)
|
||||
|
||||
-- all cols
|
||||
EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: a, b, c
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- group by all with grouping element(s) (equivalent to GROUP BY's
|
||||
-- default behavior, explicit antithesis to GROUP BY DISTINCT)
|
||||
EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a;
|
||||
QUERY PLAN
|
||||
----------------------
|
||||
HashAggregate
|
||||
Group Key: a
|
||||
-> Seq Scan on t1
|
||||
(3 rows)
|
||||
|
||||
-- verify deparsing of GROUP BY ALL
|
||||
CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL;
|
||||
SELECT pg_get_viewdef('v1'::regclass);
|
||||
pg_get_viewdef
|
||||
-----------------------
|
||||
SELECT b, +
|
||||
count(*) AS count+
|
||||
FROM t1 +
|
||||
GROUP BY ALL;
|
||||
(1 row)
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
--
|
||||
-- Test GROUP BY matching of join columns that are type-coerced due to USING
|
||||
--
|
||||
create temp table t1(f1 int, f2 int);
|
||||
|
||||
@@ -549,6 +549,60 @@ drop table t2;
|
||||
drop table t3;
|
||||
drop table p_t1;
|
||||
|
||||
--
|
||||
-- Test GROUP BY ALL
|
||||
--
|
||||
-- We don't care about the data here, just the proper transformation of the
|
||||
-- GROUP BY clause, so test some queries and verify the EXPLAIN plans.
|
||||
--
|
||||
|
||||
CREATE TEMP TABLE t1 (
|
||||
a int,
|
||||
b int,
|
||||
c int
|
||||
);
|
||||
|
||||
-- basic example
|
||||
EXPLAIN (COSTS OFF) SELECT b, COUNT(*) FROM t1 GROUP BY ALL;
|
||||
|
||||
-- multiple columns, non-consecutive order
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b), b FROM t1 GROUP BY ALL;
|
||||
|
||||
-- multi columns, no aggregate
|
||||
EXPLAIN (COSTS OFF) SELECT a + b FROM t1 GROUP BY ALL;
|
||||
|
||||
-- check we detect a non-top-level aggregate
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + 4 FROM t1 GROUP BY ALL;
|
||||
|
||||
-- including grouped column is okay
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + a FROM t1 GROUP BY ALL;
|
||||
|
||||
-- including non-grouped column, not so much
|
||||
EXPLAIN (COSTS OFF) SELECT a, SUM(b) + c FROM t1 GROUP BY ALL;
|
||||
|
||||
-- all aggregates, should reduce to GROUP BY ()
|
||||
EXPLAIN (COSTS OFF) SELECT COUNT(a), SUM(b) FROM t1 GROUP BY ALL;
|
||||
|
||||
-- likewise with empty target list
|
||||
EXPLAIN (COSTS OFF) SELECT FROM t1 GROUP BY ALL;
|
||||
|
||||
-- window functions are not to be included in GROUP BY, either
|
||||
EXPLAIN (COSTS OFF) SELECT a, COUNT(a) OVER (PARTITION BY a) FROM t1 GROUP BY ALL;
|
||||
|
||||
-- all cols
|
||||
EXPLAIN (COSTS OFF) SELECT *, count(*) FROM t1 GROUP BY ALL;
|
||||
|
||||
-- group by all with grouping element(s) (equivalent to GROUP BY's
|
||||
-- default behavior, explicit antithesis to GROUP BY DISTINCT)
|
||||
EXPLAIN (COSTS OFF) SELECT a, count(*) FROM t1 GROUP BY ALL a;
|
||||
|
||||
-- verify deparsing of GROUP BY ALL
|
||||
CREATE TEMP VIEW v1 AS SELECT b, COUNT(*) FROM t1 GROUP BY ALL;
|
||||
SELECT pg_get_viewdef('v1'::regclass);
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--
|
||||
-- Test GROUP BY matching of join columns that are type-coerced due to USING
|
||||
--
|
||||
|
||||
Reference in New Issue
Block a user