-
-
Notifications
You must be signed in to change notification settings - Fork 270
Implement SQL grouping extensions: ROLLUP, CUBE, GROUPING SETS, GROUPING(), GROUP BY DISTINCT #9029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
livius2
wants to merge
13
commits into
FirebirdSQL:master
Choose a base branch
from
livius2:grouping_sets__flattened
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
c806e55
Implemented SQL support for advanced grouping:
livius2 6452298
Merge branch 'master' into grouping_sets__flattened
livius2 b36ac24
deleting an unnecessarily copied comment
livius2 6f17370
Merge branch 'master' into grouping_sets__flattened
livius2 303b681
update pares conflicts txt
livius2 0e50834
Update grouping sets documentation to mention that GROUPING SETS may …
livius2 d0b6e7c
Use a single GroupingNode for GROUPING and GROUPING_ID, sharing valid…
livius2 4a3d3af
Merge branch 'master' into grouping_sets__flattened
livius2 8a16dd9
Reuse quantifier_opt for GROUP BY duplicate mode
livius2 7fede78
Use member initializers in grouping nodes
livius2 cfc8434
Use nullptr
livius2 3282fff
Use bool for grouping set distinct mode
livius2 25eb2a9
Move grouping legacy list maintenance out of parser
livius2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,257 @@ | ||
| # Grouping Sets | ||
|
|
||
| `ROLLUP`, `CUBE` and `GROUPING SETS` extend `GROUP BY` with multiple grouping | ||
| levels in a single query. They are useful for subtotals, grand totals and | ||
| cross-tab style summaries. | ||
|
|
||
| The related `GROUPING(<expr> [, <expr> ...])` function returns `0` when a | ||
| single `<expr>` participates in the current grouping set, and `1` when it has | ||
| been replaced by a subtotal `NULL`. With multiple arguments it returns these | ||
| bits as a single integer. `GROUPING_ID(<expr> [, <expr> ...])` is an equivalent | ||
| Firebird extension for the bit-mask form. | ||
|
|
||
| ## Syntax | ||
|
|
||
| ``` | ||
| <group by clause> ::= | ||
| GROUP BY [ALL | DISTINCT] <grouping element> [, <grouping element> ...] | ||
|
|
||
| <grouping element> ::= | ||
| <value expression> | ||
| | (<value expression> [, <value expression> ...]) | ||
| | () | ||
| | ROLLUP(<grouping element> [, <grouping element> ...]) | ||
| | CUBE(<grouping element> [, <grouping element> ...]) | ||
| | GROUPING SETS(<grouping set> [, <grouping set> ...]) | ||
|
|
||
| <grouping set> ::= | ||
| <value expression> | ||
| | (<value expression> [, <value expression> ...]) | ||
| | () | ||
| | ROLLUP(<grouping element> [, <grouping element> ...]) | ||
| | CUBE(<grouping element> [, <grouping element> ...]) | ||
| | GROUPING SETS(<grouping set> [, <grouping set> ...]) | ||
|
|
||
| <grouping function> ::= | ||
| GROUPING(<value expression> [, <value expression> ...]) | ||
| | GROUPING_ID(<value expression> [, <value expression> ...]) | ||
| ``` | ||
|
|
||
| `GROUP BY ()` specifies a single empty grouping set, producing one aggregate | ||
| group for the whole input, including empty input. | ||
|
|
||
| ## ROLLUP | ||
|
|
||
| `ROLLUP(a, b, c)` expands to: | ||
|
|
||
| ``` | ||
| (a, b, c) | ||
| (a, b) | ||
| (a) | ||
| () | ||
| ``` | ||
|
|
||
| Composite grouping items are treated as one rollup unit. For example, | ||
| `ROLLUP(a, (b, c), d)` expands to: | ||
|
|
||
| ``` | ||
| (a, b, c, d) | ||
| (a, b, c) | ||
| (a) | ||
| () | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ```sql | ||
| select | ||
| department, | ||
| product, | ||
| grouping(department) as g_department, | ||
| grouping(product) as g_product, | ||
| sum(amount) as total_amount | ||
| from sales | ||
| group by rollup(department, product) | ||
| order by | ||
| grouping(department), | ||
| department, | ||
| grouping(product), | ||
| product; | ||
| ``` | ||
|
|
||
| ## CUBE | ||
|
|
||
| `CUBE(a, b, c)` expands to all subsets: | ||
|
|
||
| ``` | ||
| (a, b, c) | ||
| (a, b) | ||
| (a, c) | ||
| (a) | ||
| (b, c) | ||
| (b) | ||
| (c) | ||
| () | ||
| ``` | ||
|
|
||
| Composite grouping items are also supported. `CUBE((a, b), c)` expands to: | ||
|
|
||
| ``` | ||
| (a, b, c) | ||
| (a, b) | ||
| (c) | ||
| () | ||
| ``` | ||
|
|
||
| Because `CUBE` grows exponentially, Firebird rejects statements producing more | ||
| than 4096 grouping sets. | ||
|
|
||
| ## GROUPING SETS | ||
|
|
||
| `GROUPING SETS` lists grouping sets explicitly and preserves their order: | ||
|
|
||
| ```sql | ||
| select a, b, sum(x) | ||
| from t | ||
| group by grouping sets ((a, b), (a), ()); | ||
| ``` | ||
|
|
||
| `GROUPING SETS` may be nested inside another `GROUPING SETS` clause. Nested | ||
| grouping sets are expanded in place, preserving order and duplicates: | ||
|
|
||
| ```sql | ||
| select a, b, c, sum(x) | ||
| from t | ||
| group by grouping sets ((a), grouping sets ((b), (c)), ()); | ||
| ``` | ||
|
|
||
| is equivalent to: | ||
|
|
||
| ``` | ||
| (a) | ||
| (b) | ||
| (c) | ||
| () | ||
| ``` | ||
|
|
||
| Top-level grouping elements are combined as a Cartesian product. For example: | ||
|
|
||
| ```sql | ||
| select a, b, c, sum(x) | ||
| from t | ||
| group by a, grouping sets ((b), (c)); | ||
| ``` | ||
|
|
||
| is equivalent to: | ||
|
|
||
| ``` | ||
| (a, b) | ||
| (a, c) | ||
| ``` | ||
|
|
||
| ## ALL and DISTINCT | ||
|
|
||
| `ALL` preserves duplicate grouping sets. This is the default. | ||
|
|
||
| ```sql | ||
| select a, sum(x) | ||
| from t | ||
| group by all grouping sets ((a), (a)); | ||
| ``` | ||
|
|
||
| `DISTINCT` removes duplicate grouping sets before execution: | ||
|
|
||
| ```sql | ||
| select a, sum(x) | ||
| from t | ||
| group by distinct grouping sets ((a), (a)); | ||
| ``` | ||
|
|
||
| ## GROUPING() | ||
|
|
||
| `GROUPING(<expr> [, <expr> ...])` may be used in the select list, `HAVING` and | ||
| `ORDER BY`. Its arguments must match grouping expressions from `ROLLUP`, `CUBE` | ||
| or `GROUPING SETS`. | ||
|
|
||
| It is not allowed in `WHERE`, in `GROUP BY`, in aggregate function arguments or | ||
| without an extended grouping context. The same rules apply to `GROUPING_ID`. | ||
|
|
||
| With one argument, `GROUPING` returns an `INTEGER` flag. Example distinguishing | ||
| a real `NULL` from a subtotal `NULL`: | ||
|
|
||
| ```sql | ||
| create table t (a integer, x integer); | ||
|
|
||
| insert into t values (null, 10); | ||
| insert into t values (1, 20); | ||
|
|
||
| select | ||
| a, | ||
| grouping(a) as g_a, | ||
| sum(x) as sx | ||
| from t | ||
| group by rollup(a) | ||
| order by grouping(a), a; | ||
| ``` | ||
|
|
||
| Result: | ||
|
|
||
| ``` | ||
| A G_A SX | ||
| <null> 0 10 | ||
| 1 0 20 | ||
| <null> 1 30 | ||
| ``` | ||
|
|
||
| Rows returned without `ORDER BY` do not have a guaranteed order. | ||
|
|
||
| Window functions are evaluated after the grouped result has been produced. | ||
| They may appear in the same query block as `ROLLUP`, `CUBE` or | ||
| `GROUPING SETS`, and they can also be applied in an outer query over a grouped | ||
| result. | ||
|
|
||
| With multiple arguments, `GROUPING` returns a `BIGINT` mask. The rightmost | ||
| argument is the least significant bit, the same as `GROUPING_ID`. This form | ||
| implements SQL optional feature T433, multi-argument `GROUPING`: | ||
|
|
||
| ```sql | ||
| select | ||
| department, | ||
| product, | ||
| grouping(department, product) as gid, | ||
| sum(amount) as total_amount | ||
| from sales | ||
| group by rollup(department, product) | ||
| order by gid, department, product; | ||
| ``` | ||
|
|
||
| ## GROUPING_ID() | ||
|
|
||
| `GROUPING_ID(<expr> [, <expr> ...])` returns the same bit mask as `GROUPING`. | ||
| With one argument it returns an `INTEGER` flag, and with multiple arguments it | ||
| returns a `BIGINT` mask. For each argument, the corresponding bit is `0` when | ||
| the expression is present in the current grouping set and `1` when it is rolled | ||
| up. The last argument is the least significant bit. | ||
|
|
||
| Example: | ||
|
|
||
| ```sql | ||
| select | ||
| department, | ||
| product, | ||
| grouping_id(department, product) as gid, | ||
| sum(amount) as total_amount | ||
| from sales | ||
| group by rollup(department, product) | ||
| order by gid, department, product; | ||
| ``` | ||
|
|
||
| For `ROLLUP(department, product)`, `GROUPING_ID(department, product)` returns: | ||
|
|
||
| ``` | ||
| 0 for (department, product) | ||
| 1 for (department) | ||
| 3 for () | ||
| ``` | ||
|
|
||
| `GROUPING_ID` accepts at most 63 arguments. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.