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 ║ ║
╚═════╩══════════╩════╩════╩
Advertisement
Answer
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
.