ruk·si

🐘 PostgreSQL
Arrays

Updated at 2015-09-26 20:36

PostgreSQL has good support for array types.

SELECT array_prepend(1, ARRAY[2,3]);        -- => {1,2,3}
SELECT array_append(ARRAY[1,2], 3);         -- => {1,2,3}
SELECT array_cat(ARRAY[1,2], ARRAY[3,4]);   -- => {1,2,3,4}
SELECT array_length(ARRAY[1,2,3,4], 1);     -- => 4 (1 is dimension)

SELECT 1 = any(ARRAY[1,2,3]);               -- => true
SELECT 4 = any(ARRAY[1,2,3]);               -- => false
SELECT 4 != all(ARRAY[1,2,3]);              -- => true
SELECT 4 != all(ARRAY[1,2,3,4]);            -- => false

SELECT ARRAY[1,2]   && ARRAY[2,4];          -- => true,  overlaps
SELECT ARRAY[1,2]   && ARRAY[3,4];          -- => false, doesn't overlap
SELECT ARRAY[1,4,3] @> ARRAY[3,1];          -- true, contains
SELECT ARRAY[2,7]   <@ ARRAY[1,7,4,2,6];    -- true, contained by

SELECT json_agg(customer_id) FROM customer;  -- turn rows to JSON array
SELECT array_agg(customer_id) FROM customer; -- turn rows to array
SELECT unnest(ARRAY[1,2]);                   -- expand array to rows
-- 1
-- 2

You can use array types as column. They are not as performant as joined tables but might be better for some cases.

CREATE TABLE employee (
    name            text,
    pay_by_quarter  integer[],      -- array
    schedule        text[][]        -- multi-dimensional array
);

Input and output syntax is '{{1,2,3},{4,5,6},{7,8,9}}'. Input can also be done using ARRAY-syntax.

INSERT INTO employee VALUES (
    'Bill',
    '{10000, 10000, 11000, 11000}',
    '{{"meeting", "lunch"}, {"training", "presentation"}}'
);

INSERT INTO employee VALUES (
    'Bill',
    ARRAY[10000, 10000, 11000, 11000],
    ARRAY[['meeting', 'lunch'], ['training', 'presentation']]
);

Array elements can be accessed with []. Note that indexing starts at 1, not 0.

SELECT pay_by_quarter[3] FROM employee;
-- => 11000

SELECT name
FROM employee
WHERE pay_by_quarter[1] = pay_by_quarter[2];
-- => Bill

Arrays support slicing. Creates a subarray.

SELECT pay_by_quarter[2:3]
FROM employee
WHERE name = 'Bill';
-- => {10000,11000}

Editing arrays is pretty straight forward.

UPDATE employee
SET pay_by_quarter = '{10000,10000,11000,13000}'
WHERE name = 'Bill';
-- => {10000,10000,11000,13000}

UPDATE employee
SET pay_by_quarter[2:3] = '{11000, 12000}'
WHERE name = 'Bill';
-- => {10000,11000,12000,13000}

UPDATE employee
SET pay_by_quarter[4] = 14000
WHERE name = 'Bill';
-- => {10000,11000,12000,14000}

UPDATE employee
SET pay_by_quarter[5] = 17000
WHERE name = 'Bill';
-- => {10000,11000,12000,14000,17000}

UPDATE employee
SET pay_by_quarter[7] = 20000
WHERE name = 'Bill';
-- => {10000,11000,12000,14000,17000,NULL,20000}

generate_subscripts is handly for complex array lookups.

SELECT *
FROM (
  SELECT
    name,
    pay_by_quarter,
    generate_subscripts(pay_by_quarter, 1) AS found_in
  FROM employee
) AS foo
WHERE pay_by_quarter[found_in] = 12000;
-- name    pay_by_quarter                                found_in
-- "Bill", "{10000,11000,12000,12000,17000,NULL,20000}", 3
-- "Bill", "{10000,11000,12000,12000,17000,NULL,20000}", 4

Sources