aggregation_function(expression, ORDER BY a) - в начале сортирует таблицу по а, затем применяет aggregation_function к получившемуся списку.
Да, только запятая в скобках лишняя. Такой синтаксис позволяет иметь агрегатам в списке SELECT сортировку входных значение (напомню, что ORDER BY в запросе вычисляется после GROUP BY и агрегации, т.е. чтобы раньше так сделать, был нужен подзапрос, который отсортирует массив данных), даже каждому агрегату свою (раньше вообще нельзя было сделать нормально). Агрегатным функциям часто не важен порядок входных значений (COUNT, SUM, MAX - не зависят от порядка), но есть функции, для которых он значение имеет (string_agg, etc, можно свои также написать).
А что делает aggregation_function(expression), WITHIN GROUP (ORDER BY a)
Это синтаксис для специального вида агрегатов: Ordered-Set Aggregate Functions и Hypothetical-Set Aggregate Functions (запятая тут у вас тоже лишняя). Обычные с ним не заработают.
Они принимают на вход отсортированный массив данных, указанный в ORDER BY (т.е.
a, а не expression!), плюс, возможно, значение expression (вычисляется один раз за запрос).
Область применения пока достаточно специфична: Ordered-Set Aggregate Functions по сути применяется только для вычисления перцентилей (зато их стало легко и приятно считать:
SELECT percentile_disc (0.2) WITHIN GROUP (ORDER BY ...)
).
Hypothetical-Set Aggregate Functions - это такие аналоги некоторых WINDOW агрегатов (типа rank):
SELECT rank() OVER (ORDER BY value) ...; -- вернет ранк данной записи в отсортированном по value списке
SELECT rank(55) WITHIN GROUP (ORDER BY value) ...; -- вернет ранк числа 55, как если бы оно было в отсортированном по value списке
В общем, штука своеобразная. Читайте документацию, сходу может быть трудно понять.