Если я правильно понимаю ваши требования, то «логические операции», вероятно, не лучший способ описать их;они действительно устанавливают операции пересечения и объединения (хотя эти два тесно связаны).
Операторы диапазона Postgres могут вычислять объединения и пересечения, поэтому это может помочь начать с объединения парыметки времени начала / конца (как в ваш предыдущий вопрос ) для построения tsrange
значений .
Как только это будет на месте, нахождение пересечения (A & B
) будетотносительно просто:
WITH time_pair AS (
SELECT *, lead("time") OVER (PARTITION BY mobile ORDER BY "time") AS next_time
FROM events
WHERE event IN ('START', 'STOP')
),
time_range AS (
SELECT mobile, tsrange("time", next_time) AS period
FROM time_pair
WHERE event = 'START'
)
SELECT 'A & B', a_range.period * b_range.period
FROM time_range a_range
JOIN time_range b_range ON
a_range.period && b_range.period
WHERE
a_range.mobile = 'A' AND
b_range.mobile = 'B';
Объединение (A | B
) немного сложнее;если диапазон перекрывается на обоих концах, то для каждой выходной строки есть (как минимум) три диапазона, поэтому одного JOIN
будет недостаточно.
С другой стороны, эта проблема заключается внемного более общий, поскольку вы можете просто объединить любые перекрывающиеся диапазоны без учета того, от какого именно пользователя они произошли, так что будет немного проще найти существующие реализации. Этот ответ кажется довольно полным.Вы можете найти еще несколько, выполнив поиск "postgres агрегирование диапазона" .