Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aggregate strings in descending order in a PostgreSQL query

In addition to the question How to concatenate strings of a string field in a PostgreSQL 'group by' query?

How can I sort employee in descending order?

I am using PostgreSQL 8.4 which doesn't support string_agg(). I've tried to use the following, but it isn't supported:

array_to_string(array_agg(employee ORDER BY employee DESC), ',')

I'd appreciate any hint to the right answer.

like image 458
David Avatar asked May 06 '12 12:05

David


People also ask

How do I get descending order in PostgreSQL?

When sorting your result set in descending order, you use the DESC attribute in your ORDER BY clause as follows: SELECT last_name, first_name, city FROM contacts WHERE first_name = 'Joe' ORDER BY last_name DESC; This PostgreSQL ORDER BY example would return all records sorted by the last_name field in descending order.

Can I use aggregate function in ORDER BY?

An aggregate function cannot be used directly in: an ORDER BY clause. Attempting to do so generates an SQLCODE -73 error. However, you can use an aggregate function in an ORDER BY clause by specifying the corresponding column alias or selectItem sequence number.

What is array AGG in PostgreSQL?

PostgreSQL ARRAY_AGG() function is an aggregate function that accepts a set of values and returns an array where each value in the input set is assigned to an element of the array. Syntax: ARRAY_AGG(expression [ORDER BY [sort_expression {ASC | DESC}], [...]) The ORDER BY clause is an voluntary clause.

How do I write ascending order in PostgreSQL?

Use the ASC option to sort rows in ascending order and DESC option to sort rows in descending order. The ORDER BY clause uses the ASC option by default. Use NULLS FIRST and NULLS LAST options to explicitly specify the order of NULL with other non-null values.


1 Answers

In PostgreSQL 9.0 or later you can order elements inside aggregate functions:

SELECT company_id, string_agg(employee, ', ' ORDER BY company_id DESC)::text
FROM   tbl
GROUP  BY 1;

Neither string_agg() nor that ORDER BY are available for PostgreSQL 8.4. You have to pre-order values to be aggregated. Use a subselect or CTE (pg 8.4+) for that:

SELECT company_id, array_to_string(array_agg(employee), ', ')
FROM  (SELECT * FROM tbl ORDER BY company_id, employee DESC) x
GROUP  BY 1;

I order by company_id in addition as that should speed up the subsequent aggregation.

Less elegant, but faster. (Still true for Postgres 14.)

See:

  • Concatenate multiple result rows of one column into one, group by another column
  • Alternatives to array_agg()?
like image 60
Erwin Brandstetter Avatar answered Oct 08 '22 15:10

Erwin Brandstetter