Skip to content
Advertisement

How to query all rows where a given column matches at least all the values in a given array with PostgreSQL?

The request below:

SELECT foos.id,bars.name
FROM foos
JOIN bar_foo ON (bar_foo.foo_id = id )
JOIN bars ON (bars.id = bar_foo.bar_id )

returns a list like this:

id | name
---+-----
 1 | a
 1 | b
 2 | a
 2 | y
 2 | z
 3 | a
 3 | b
 3 | c
 3 | d

How to get the ids for which id must have at least a and b, and more generally the content of a given array ?

From the example above, I would get:

id | name
---+-----
 1 | a
 1 | b
 3 | a
 3 | b
 3 | c
 3 | d

Advertisement

Answer

For two values, you can use windowing boolean aggregation:

select *
from (
    select f.id, b.name, 
        bool_or(b.name = 'a') over(partition by id) has_a,
        bool_or(b.name = 'b') over(partition by id) has_b
    from foos f
    join bar_foo bf on bf.foo_id = f.id
    join bars b on b.id = bf.bar_id
) t
where has_a and has_b

A more generic approach uses array aggregation:

select *
from (
    select f.id, b.name, 
        array_agg(b.name) over(partition by id) arr_names
    from foos f
    join bar_foo bf on bf.foo_id = f.id
    join bars b on b.id = bf.bar_id
) t
where arr_names @> array['a', 'b'] 
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement