Search code examples
sqlamazon-redshiftstring-aggregation

Redshift SQL to comma separate a field with GROUP


I want to comma separate a fields values and GROUP BY two other fields in Redshift.

Sample data:

table_schema table_name column_name 
G1           G2         a
G1           G2         b
G1           G2         c
G1           G2         d
G3           G4         x
G3           G4         y
G3           G4         z

Expected Output:

table_schema table_name column_name 
G1           G2         a, b, c, d
G3           G4         x, y, z

I can do this in MSSQL like so:

SELECT table_schema, table_name, column_name = 
    STUFF((SELECT ', ' + column_name
           FROM your_table b 
           WHERE b.table_schema = a.table_schema AND b.table_name = a.table_name
          FOR XML PATH('')), 1, 2, '')
FROM information_schema.tables t
INNER JOIN information_schema.columns c on c.table_name = t.table_name AND c.table_schema = t.table_schema
GROUP BY table_schema, table_name

And in PostgreSQL this would be:

SELECT table_schema, table_name, String_agg(column_name, ',')
FROM information_schema.tables t
INNER JOIN information_schema.columns c on c.table_name = t.table_name AND c.table_schema = t.table_schema
GROUP BY table_schema, table_name

But Redshift doesn't contain the STRING_AGG function.

I cannot figure out how to do this in Redshift.

EDIT

Using the answer from here does NOT WORK:

SELECT CUST_ID,
       LISTAGG("ORDER", ', ')
WITHIN GROUP (ORDER BY "ORDER")
OVER (PARTITION BY CUST_ID) AS CUST_ID
FROM Table
ORDER BY CUST_ID

My Version:

SELECT t.table_name, LISTAGG("column_name", ', ')
WITHIN GROUP (ORDER BY "column_name")
OVER (PARTITION BY t.table_name) AS table_schema
FROM information_schema.columns t
ORDER BY t.table_name

It gives me the following error:

0A000: Specified types or functions (one per INFO message) not supported on Redshift tables.

Which I don't understand as I am only selecting from a single node?


Solution

  • SELECT t.CUST_ID, c.orders
    FROM Table t
             JOIN
         (SELECT cust_id,
                 LISTAGG("ORDER"::text, ', ')
                 WITHIN GROUP (ORDER BY "ORDER") as orders
          FROM table t
          GROUP BY cust_id) c
         ON t.cust_id = c.cust_id
    ORDER BY CUST_ID;