Return column name and distinct values

前端 未结 3 2042
生来不讨喜
生来不讨喜 2021-01-22 02:09

Say I have a simple table in postgres as the following:

+--------+--------+----------+
|  Car   |  Pet   |   Name   |
+--------+--------+----------+
| BMW    |           


        
3条回答
  •  迷失自我
    2021-01-22 02:55

    It's bad style to put set-returning functions in the SELECT list and not allowed in the SQL standard. Postgres supports it for historical reasons, but since LATERAL was introduced Postgres 9.3, it's largely obsolete. We can use it here as well:

    SELECT x.col, x.val
    FROM   tbl, LATERAL (VALUES ('car', car)
                              , ('pet', pet)
                              , ('name', name)) x(col, val)
    GROUP  BY 1, 2
    ORDER  BY 1, 2;
    

    You'll find this LATERAL (VALUES ...) technique discussed under the very same question on dba.SE you already found yourself. Just don't stop reading at the first answer.

    Up until Postgres 9.4 there was still an exception: "parallel unnest" required to combine multiple set-returning functions in the SELECT list. Postgres 9.4 brought a new variant of unnest() to remove that necessity, too. More:

    • Unnest multiple arrays in parallel

    The new function is also does not derail into a Cartesian product if the number of returned rows should not be exactly the same for all set-returning functions in the SELECT list, which is (was) a very odd behavior. The new syntax variant should be preferred over the now outdated one:

    SELECT DISTINCT x.*
    FROM   tbl t, unnest('{car, pet, name}'::text[]
                       , ARRAY[t.car, t.pet, t.name]) AS x(col, val)
    ORDER  BY 1, 2;
    

    Also shorter and faster than two unnest() calls in parallel.

    Returns:

     col  |  val
    ------+--------
     car  | BMW
     car  | Honda
     car  | Toyota
     name | Mary
     name | Sam
     pet  | Cat
     pet  | Dog
    

    DISTINCT or GROUP BY, either is good for the task.

提交回复
热议问题