Search code examples
arrayspostgresqlrails-postgresql

How to convert the result of intersection of two arrays into integer Array from a SQL query to an Integer array in postgresql


Query 1:

SELECT ARRAY(select id from contacts where id = 0)::INT[],
       ARRAY[]::INT[],
       ARRAY(SELECT id FROM contacts WHERE id = 0)::INT[] = ARRAY[]::int[]

Produces this result:

int4    array   ?column?                                                                    
{}      {}      TRUE

Query 2:

SELECT (ARRAY(SELECT id FROM contacts WHERE id = 0)::INT[]
      & ARRAY(select id from contacts where id = 0)::INT[]),
        ARRAY[]::INT[],
       (ARRAY(SELECT id FROM contacts WHERE id = 0)::INT[]
      & ARRAY(SELECT id FROM contacts WHERE id = 0)::INT[]) = ARRAY[]::int[]

Produces a different result:

?column?    array   ?column?                                                            
{}              {}      FALSE

Why the difference?

Is there any other way to compare an empty integer array with the result of an intersection of two arrays like in the second query?


Solution

  • Standard PostgreSQL does not support the ARRAY intersection operator. You must have installed the additional module intarray.

    Your question boils down to this:
    The intersection of two empty integer arrays yields an empty integer array. Why does this query yield false?

    SELECT ('{}'::int[] & '{}'::int[]) = '{}'::int[]
    

    Or in other syntax, meaning the same:

    SELECT (ARRAY[]::int[] & ARRAY[]::int[]) = ARRAY[]::int[]
    

    While this yields true:

    SELECT '{}'::int[] = '{}'::int[]
    

    And yes, that is a very good question.


    For what it's worth, I can explain the difference:

    SELECT array_dims('{}'::int[])
    <NULL>
    
    SELECT array_dims('{}'::int[] & '{}'::int[])
    [1:0]
    

    In other words, the first one is just an empty array, while the second one is a one-dimensional array with an empty element.

    This can be very confusing. For instance see this thread about how to treat string_to_array() with empty output.
    I am not sure the & operator does the right thing here.