Search code examples
sqlpostgresqlunpivot

Postgresql query to transpose columns to rows


I have a table like this one:

id_edifc classe_a classe_b classe_c
9001 0 0 1
9002 1 1 1
9003 0 1 2
9004 0 0 0
9005 1 1 0

and I would like to visualize it like this instead:

id_edifc classe
9001 classe_c
9002 classe_a
9002 classe_b
9002 classe_c
9003 classe_b
9003 classe_c
9003 classe_c
9004 NULL
9005 classe_a
9005 classe_b

Solution

  • Using LATERAL:

    SELECT t.id_edifc, s.name
    FROM tab t
    ,LATERAL ( VALUES (classe_a, 'classe_a')
                     ,(classe_b, 'classe_b')
                     ,(classe_c, 'classe_c'))s(val, name)
    WHERE val = 1;
    

    To handle all zeros in row and replicating values:

    SELECT t.id_edifc, s2.name
    FROM tab t
    LEFT JOIN LATERAL (SELECT s.name
                      FROM (VALUES  (classe_a, 'classe_a')
                                   ,(classe_b, 'classe_b')
                                   ,(classe_c, 'classe_c'))s(val, name)
                       ,LATERAL generate_series(1,s.val)
                       WHERE val > 0
                     ) s2 ON TRUE
    ORDER BY t.id_edifc;
    

    db<>fiddle demo

    Output:

    +-----------+----------+
    | id_edifc  |   name   |
    +-----------+----------+
    |     9001  | classe_c |
    |     9002  | classe_a |
    |     9002  | classe_b |
    |     9002  | classe_c |
    |     9003  | classe_b |
    |     9003  | classe_c |
    |     9003  | classe_c |
    |     9004  | NULL     |
    |     9005  | classe_a |
    |     9005  | classe_b |
    +-----------+----------+