I have a database query like:
SELECT
Foo,
Foo2,
some_calc as Bar,
some_other_calc as Bar2,
From
FooBar
-- some inner joins for the calcs
GROUP BY FOO
ORDER BY Bar DESC, Bar2 DESC;
I want to order by database with the order query, and then group together FOO
s so that that first grouped block contains the FOO
with the greatest Bar. The second grouped block of FOO
s contains the seconds highest Bar, etc.
But this doesn't work as Postgres doesn't allow random grouping:
column "Bar" must appear in the GROUP BY clause or be used in an aggregate function
.
How can I fix this?
Sample data and output:
╔═════╦══════════╦════╦════╦
║ FO ║ Bar ║ Bar 2 ║
╠═════╬══════════╬═════════╬
║ 6 ║ 10 ║ ║
║ 4 ║ 110 ║ ║
║ 3 ║ 120 ║ ║
║ 8 ║ 140 ║ ║
║ 3 ║ 180 ║ ║
║ 3 ║ 190 ║ ║
╚═════╩══════════╩════╩════╩
Output:
╔═════╦══════════╦════╦════╦
║ FO ║ Bar ║ Bar 2 ║
╠═════╬══════════╬═════════╬
║ 3 ║ 190 ║ ║
║ 3 ║ 180 ║ ║
║ 3 ║ 120 ║ ║
║ 8 ║ 140 ║ ║
║ 4 ║ 110 ║ ║
║ 6 ║ 10 ║ ║
╚═════╩══════════╩════╩════╩
Both GROUP BY and ORDER BY are clauses (or statements) that serve similar functions; that is to sort query results. However, each of these serve very different purposes; so different in fact, that they can be employed separately or together.
In the query, GROUP BY clause is placed after the WHERE clause. In the query, GROUP BY clause is placed before ORDER BY clause if used any.
group by does not order the data neccessarily. A DB is designed to grab the data as fast as possible and only sort if necessary. So add the order by if you need a guaranteed order.
Yes, the ORDER BY is necessary, unless you don't actually care about the order. Just because you observe some type of sorting does not make it guaranteed.
SELECT foo, <some calc> AS bar, bar2
FROM foobar
ORDER BY max(<some calc>) OVER (PARTITION BY foo) DESC NULLS LAST -- can't refer to bar
, bar DESC NULLS LAST -- but you can here
, foo DESC NULLS LAST;
bar
does not have to be a column, can be any valid expression, even an aggregate function (in combination with GROUP BY
) - just not another window function, which can't be nested. Example:
You cannot, however, refer to a column alias (output column name) on the same query level within a window function. You have to spell out the expression again, or move the calculation to a subquery or CTE.
You can refer to output column names in ORDER BY
and GROUP BY
otherwise (but not in the WHERE
or HAVING
clause). Explanation:
Since it has not been defined we must expect NULL values. Typically you want NULL values last, so add NULLS LAST
in descending order. See:
Assuming you want bigger foo
first in case of ties with bar
.
You just want order by
. Group by
reduces (in general) the number of rows by aggregation.
You can accomplish this using window functions:
SELECT Foo, Bar, Bar2,
From FooBar
ORDER BY MAX(Bar) OVER (PARTITION BY Foo) DESC,
Foo;
Shouldn't this do what you're asking for?
If not, it would help if you could give some sample data in the query and show how you'd want it as the output.
SELECT
Foo,
MAX(some_calc) as Bar,
MAX(some_other_calc) as Bar2,
From
FooBar
##some inner joins for the calcs
GROUP BY FOO;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With