Полусложный доктринальный запрос - PullRequest
0 голосов
/ 17 сентября 2011

У меня есть запрос, чтобы написать, что это слишком сложно для меня, чтобы понять.Помощь будет оценена.По сути, моя таблица:

Table: Foo
Columns: id
         timestamp
         bar1
         bar2
         bar3

Bar1, bar2 и bar3 не являются уникальными для каждой записи.На самом деле, комбинация из 3 специально относится к нескольким записям.Например:

0 | 2011-01-01 00:01:01 | 100 | 5 | 'Hello'
1 | 2011-01-01 12:12:00 | 100 | 5 | 'Hello'
2 | 2011-01-01 07:43:00 | 101 | 8 | 'Monkey'
3 | 2011-01-01 17:46:08 | 102 | 9 | 'Cat'
4 | 2011-01-01 23:15:00 | 100 | 5 | 'Hello'
5 | 2011-01-01 10:00:00 | 100 | 6 | 'Goodbye'

Записи 0, 1 и 4 связаны между собой, а 2, 3 и 5 являются уникальными.

Имея это в виду, я хотел бы найти все записи с bar1 == 100, bar2 == 5 и bar3 == 'Hello', IF все записи в группе имеютотметка времени <= текущее время <strong>ИЛИ одна из записей в группе имеет отметку времени <= до текущего времени - 30 минут. </p>

Надеюсь, это имеет смысл.Если это не так, просто дайте мне знать, и я сделаю все возможное, чтобы уточнить.

Редактировать : Я надеялся, что для примера будет достаточно иметь только бар, ноНа самом деле моя фактическая таблица имеет несколько столбцов, которые должны совпадать, чтобы указать, что запись связана.Я обновил пример соответственно.

Ответы [ 2 ]

1 голос
/ 17 сентября 2011

Если я правильно понимаю ваш вопрос, вы ХОТИТЕ все записи для (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

Если мое первое предположение о ваших входных параметрах неверно, вы, конечно, можете добавить фильтр к каждому подходящему этапу запроса.Конечно, фильтрация на предыдущих этапах будет более эффективной.Я добавил подходящие комментарии.

0 голосов
/ 17 сентября 2011

Я не очень знаком с postgresql, но вот ответ на T-SQL, который должен возвращать результаты, которые вы ищете.Я не думаю, что он использует какие-либо команды, которые недоступны в postgresql, но я не уверен.Кроме того, он может подавить DISTINCT в под-выборе, если это так, просто удалите его, так как это не нужно.Удачи.

SELECT *
FROM Foo
WHERE 
(
bar IN (SELECT bar 
        FROM (SELECT bar, MAX(timestamp) As HighestTime FROM Foo GROUP BY bar) HT 
        WHERE HT.HighestTime <= GETDATE())
OR bar IN (SELECT DISTINCT bar FROM Foo WHERE timestamp <= DATEADD(mm, -30, GETDATE())
) 
AND
bar = 100

Первый «бар в» использует подвыбор, чтобы получить только те номера баров, у которых ВСЕ отметки времени меньше или равны текущей дате и времени, просто отметив самую большую.*

Второй «бар в» использует подвыбор для получения любых номеров баров, которые имеют по крайней мере 1 запись с отметкой времени, меньшей или равной текущему времени - 30 минут.

Панель «Бар»= "просто ограничивает его конкретным номером бара.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...