I've got 3 tables:
create table events (id serial, ...)
create table devices (id serial, ...)
create table event_devices (event_id int, device_id int, ...)
Let's say the data in event_devices looks like this:
event_id | device_id
--------------------
1 | 1
1 | 2
1 | 3
2 | 1
2 | 4
I need to conduct a search for two cases:
- filter all events that contain any device in a given list such that
{1, 4} -> (1, 2){1, 2, 3} -> (1, 2)
- filter all events that contain all devices in a given list such that
{1, 4} -> (2){1, 2, 3} -> ()
Let's say the given list is input as an array of ints.
The first case is pretty simple; I can simply use "IN":
with
devices_filter as (
select distinct
event_devices.event_id
from event_devices
where
event_devices.device_id in (select unnest($1::int[]) as device_id)
)
select
events.id as event_id
from events
left outer join devices_filter on
devices_filter.event_id = events.id
where
devices_filter.event_id is not null
But how do I query for the second case? I've thought may be I need another CTE that groups and aggregates device ids based on event id, then perform an intersection, and check that the resulting length is equal to the length of the input array, but I'm not sure exactly how that would work. I'd also like to avoid any unnecessary grouping, since the event_devices table can be quite large.
Any hints or tips?