229

I have a table:

CREATE TABLE tblproducts
(
productid integer,
product character varying(20)
)

With the rows:

INSERT INTO tblproducts(productid, product) VALUES (1, 'CANDID POWDER 50 GM');
INSERT INTO tblproducts(productid, product) VALUES (2, 'SINAREST P SYP 100 ML');
INSERT INTO tblproducts(productid, product) VALUES (3, 'ESOZ D 20 MG CAP');
INSERT INTO tblproducts(productid, product) VALUES (4, 'HHDERM CREAM 10 GM');
INSERT INTO tblproducts(productid, product) VALUES (5, 'CREAM 15 GM');
INSERT INTO tblproducts(productid, product) VALUES (6, 'KZ LOTION 50 ML');
INSERT INTO tblproducts(productid, product) VALUES (7, 'BUDECORT 200 Rotocap');

If I execute string_agg() on tblproducts:

SELECT string_agg(product, ' | ') FROM "tblproducts"

It will return the following result:

CANDID POWDER 50 GM | ESOZ D 20 MG CAP | HHDERM CREAM 10 GM | CREAM 15 GM | KZ LOTION 50 ML | BUDECORT 200 Rotocap

How can I sort the aggregated string, in the order I would get using ORDER BY product?

I'm using PostgreSQL 9.2.4.

1

3 Answers 3

382

With postgres 9.0+ you can write:

select string_agg(product,' | ' order by product) from "tblproducts"

Details here.

Sign up to request clarification or add additional context in comments.

3 Comments

can you please suggest a solution which will also work when using window functions?
Thanks for the link. Searching string_agg in the documentation doesn’t take you there.
Is it possible to keep the resulted output as it is without sorting them?
6

This seems to sort numerically even with casting:

select string_agg(cast (o.id as varchar),',' order by o.id) from tb_organisation o 
    inner join tb_country c on o.country_fk = c.id 
        where c.name ilike '%united%' group by c.id;

1 Comment

Hi, you order by o.id not the casted value, should look like: select string_agg(cast (o.id as varchar),',' order by cast (o.id as varchar))
3
select string_agg(prod,' | ') FROM 
  (SELECT product as prod FROM tblproducts ORDER BY product )MAIN;

SQL FIDDLE

5 Comments

I had the same problem as OP, and this approach was my first thought, but unfortunately it doesn't work (which brought me here), whereas Igor's does.
On my side, both approaches (Ilesh's and Igor's) worked.
Wrong answer. It might work but is not guaranteed to work.
Relational Database is based in part on mathematical sets, and this is reflected in the fact that a basic principle in SQL is that row order is not significant. Even if you were to include an ORDER BY clause in the sub query, the FROM clause doesn’t necessarily get the data in order. If this works, it is pure luck.
I was happily using this solution for a long time, until one day some data entered my system that caused this to no longer work. It's very deceptive. (though to Ilesh's defence the docs do say it will "usually" work: "Alternatively, supplying the input values from a sorted subquery will usually work")

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.