sqlpostgresql

Grouping a table by its type on different columns


I have a table with two columns (type, id) that has the following structure:

id type
A123 ACCOUNT
C123 CLIENT
O123 ORDER
A124 ACCOUNT
O124 ORDER
C125 CLIENT

I want to be able to do a SELECT on this table with alias columns of account_id_column, client_id_column and order_id_column where it groups it by type into three different columns like the following:

account_id_column client_id_column order_id_column
A123 C123 O123
A124 C125 O124

But not sure how to do this? Do I have to use a JOIN on the tables and then use a where clause on the type and then group by on it?


Solution

  • SQL queries are row based, but you want columns. This requires a pivot. We need something in common for each row so we can group them together. We can add a row_number to each row to put them in order. Then we pivot them into individual columns by grouping by the row number.

    with ordered_things as (
      select
        row_number() over(partition by type order by id asc) as rn,
        id, type
      from things
    )
    select
      coalesce(max(id) filter(where type = 'ACCOUNT'), '') as account_id,
      coalesce(max(id) filter(where type = 'CLIENT'), '') as client_id,
      coalesce(max(id) filter(where type = 'ORDER'), '') as order_id
    from ordered_things
    group by rn
    order by rn
    

    Since we know there's only one ID for each type in the group, max(id) is just a way to satisfy the need for each column of a group by query to be an aggregated function.

    coalesce just gets rid of unsightly nulls when there isn't an equal number of ids for each type.

    Demonstration.