sqlpostgresqlunnestset-returning-functions

Generate one additional row per array element


Using PostgreSQL 9.6, I'm trying to insert rows into a table map, generated from another table tbl.

tbl

name in1 in2
a 1
b 2 {3}
c 4 {5,6}
d 7 {8,9,10}

Should result in this:

map

name out1 out2
a 1 1
b 2 2
b 2 3
c 4 4
c 4 5
c 4 6
d 7 7
d 7 8
d 7 9
d 7 10

in1 and each value in the array in2 should get entries for user name. I can't figure out how best to iterate through the array, whether it's a subselect, or a built-in operator.

So far I have:

INSERT INTO map(name, out1, out2)
SELECT (name, in1, in1)
FROM
    tbl;

UPDATE map
SET out2 = 
    (loop possibly of in2?)
FROM
    tbl t
WHERE
     name = t.name;

Solution

  • Simply:

    INSERT INTO map (name, out1, out2)
    SELECT pname, in1, unnest(in1 || in2)
    FROM   tbl
    

    Assuming this table definition:

    CREATE TABLE tbl (
      pname text PRIMARY KEY
    , in1   integer NOT NULL
    , in2   integer[]  --  can be NULL?
    );
    

    fiddle

    Notably, in2 is an integer array (integer[]). Else, cast with in2::int[] - you have valid array literals on display.

    About the element-to-array concatenation in in1 || in2, see:

    in1 and in2 can be NULL, but consider corner cases demonstrated in my fiddle. You may want to move unnest() to a LATERAL subquery to steer corner cases. See:

    Careful with multiple set-returning functions like unnest() in the SELECT list, especially before Postgres 10. (Not an issue with just one.) See: