Reputation: 16311
I have a GROUP BY
Query which appears to use non-aggregated data not in the GROUP BY
clause, which I thought would not work.
I was asked to write a query which converted the following data:
| item | type | cost | category |
|------|------|------|----------|
| 1 | X | 10 | A |
| 1 | Y | 20 | A |
| 2 | X | 30 | B |
| 2 | Y | 40 | B |
| 3 | X | 50 | C |
| 3 | Y | 60 | C |
| 4 | X | 70 | D |
| 4 | Y | 80 | D |
into this:
| item | x | y | category |
|------|----|----|----------|
| 1 | 10 | 20 | A |
| 2 | 30 | 40 | B |
| 3 | 50 | 60 | C |
| 4 | 70 | 80 | D |
Note:
item
is meant to be unique, but it is repeated for each type
valuecategory
is the same for rows of the same item
I ended up with the following solution:
SELECT
item,
sum(CASE WHEN type='X' THEN cost END) as X,
sum(CASE WHEN type='Y' THEN cost END) as Y,
category
FROM data
GROUP BY item,category;
What surprised me is that it worked. What surprised me more is that it works for PostgreSQL, MariaDB (ANSI Mode), Microsoft SQL and SQLite.
Note:
- I have included category
in the GROUP BY
simply to allow it to appear in the SELECT
clause.
- I have used the sum()
function, even though there will only be one value, also simply to included it in the SELECT
clause.
I thought I would not be able to use type
column in the SELECT
column because it is not in the GROUP BY
and it is not aggregated. Indeed, if I try to select it by itself, the query will fail.
The question is, how is it that I can use the type
column with the CASE
operator, when I can’t use it by itself?
Upvotes: 0
Views: 1348
Reputation:
Your usage of the "ungrouped" columns is perfectly fine.
The rule is: "Every expression in the SELECT list must either be an aggregat function or it must part of the GROUP BY".
The column type
is used inside an aggregate. sum(CASE WHEN type='X' THEN cost END) as X
is not really different to sum(cost)
or max(type)
.
This becomes more obvious if you use the standard SQL filter
option:
sum(CASE WHEN type='X' THEN cost END)
is the same as:
sum(cost) filter (where type = 'X')
However only very few DBMS support this standard.
Upvotes: 3