Если я правильно понимаю ваш вопрос, вы ХОТИТЕ все записи для (bar1, bar2, bar3) = (100, 5, 'Hello') и вы ЕСТЬ определенный current_time
как единственный входной критерий.
В качестве первого шага я перефразирую два условия: чтобы извлечь членов группы, наибольшая временная метка группы должна быть в прошлом (ваше первое условие), или наименьшая временная метка группы должна составлять не менее 30 минут.old (эквивалент вашего второго условия).
Таким образом, вы можете просмотреть группу и ее временные метки с помощью этого запроса:
SELECT bar1, bar2, bar3, max(timestamp) group_end, min(timestamp) group_start
FROM foo
GROUP BY bar1, bar2, bar3;
Добавление фильтров: (обратите внимание на специальный синтаксис psql
для \set
и :
- это только для тестирования)
\set current_time '''2011-01-01 17:00:00'''
SELECT bar1, bar2, bar3, max(timestamp) group_end, min(timestamp) group_start
FROM foo
GROUP BY bar1, bar2, bar3
HAVING max(timestamp) <= :current_time OR min(timestamp) +'30min' <= :current_time
Это ничего не даст для current_time = 2011-01-01 00:31:00
, потому что ни одна группа не завершила работу, а незаконченный идентификатор группы недостаточно стар.После этого группа (100, 5, Hello) возвращается из-за предложения OR , а другая группа возвращается при дальнейшем увеличении current_time.
Пока все хорошо - последний фрагментчтобы получить членов всех найденных групп:
SELECT * FROM foo WHERE (bar1, bar2, bar3) in (
SELECT bar1, bar2, bar3 FROM foo
-- add WHERE clause with constraints based on bar1, bar2, bar3 here
GROUP BY bar1, bar2, bar3
HAVING max(timestamp) <= :current_time OR min(timestamp) +'30min' <= :current_time
)
-- add further constraints here
Если мое первое предположение о ваших входных параметрах неверно, вы, конечно, можете добавить фильтр к каждому подходящему этапу запроса.Конечно, фильтрация на предыдущих этапах будет более эффективной.Я добавил подходящие комментарии.