SQLite запрос ГДЕ с ВНЕШНИМ СОЕДИНЕНИЕМ - PullRequest
1 голос
/ 12 апреля 2019

Я немного заржавел с моим SQL и столкнулся с небольшой проблемой с запросом.В нашем приложении у нас есть две относительные таблицы для этой проблемы.Есть записи, и для каждой записи есть N шагов.

Мы пытаемся оптимизировать наши запросы, поэтому вместо того, чтобы постоянно запрашивать все записи, мы просто запрашиваем записи, которые были обновлены после последней проверки.Шагов может быть много, поэтому этот запрос должен просто возвращать записи и некоторые сводные данные о шагах, и мы можем отдельно запросить шаги при необходимости.

Время начала записи и время обновления рассчитываются из первого и самого последнего времени шага процесса соответственно.Мы также должны сгруппировать статусы записей.

Вот запрос, который мы собираем в python, так как его легче читать:

statement = 'SELECT e.serial_number, ' + \
                   'e.description, ' + \
                   'min(p.start_time) begin_time, ' + \
                   'group_concat(p.status) status, ' + \
                   'max(p.last_updated) last_updated, ' + \
            'FROM entries e ' + \
            'LEFT OUTER JOIN process_steps p ON e.serial_number = p.serial_number ' + \

# if the user provides a "since" date, only return entries updated after
# that date
if since is not None:
    statement += ' WHERE last_updated > "{0}"'.format(since)

statement += ' GROUP BY e.serial_number'

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

Entry: 123 foo
Steps:
    1. start time 10:00, updated 10:30, status completed
    2. start time 11:00, updated 11:30, status completed
    3. start time 12:00, updated 12:30, status failed
    4. start time 13:00, updated 13:30, status in_progress
Entry: 321 bar
Steps:
    1. start time 01:00, updated 01:30, status completed
    2. start time 02:00, updated 02:30, status completed

Если мы запросим без где, мы получим все записи.Таким образом, для этого случая он вернул бы:

321, bar, 01:00, "completed,completed", 02:30
123, foo, 10:00, "completed,completed,failed,in_progress", 13:30

Если бы у меня было время 12:15, то он вернул бы только это:

123, foo, 12:00, "failed,in_progress", 13:30

В этом результате время начала наступаетиз шага 3, а статусы только из шагов 3 и 4. Я ищу целую запись:

123, foo, 10:00, "completed,completed,failed,in_progress", 13:30

Итак, я хочу отфильтровать окончательные результаты на основе этого last_updated value, но в настоящее время он также фильтрует результаты объединения, в результате чего значения begin_time, last_updated и status отбрасываются, поскольку они рассчитываются с частичным набором шагов.Любые идеи, как изменить запрос, чтобы получить то, что я хочу здесь?

Редактировать:

Кажется, здесь также могут быть некоторые проблемы с именами.Имена, которые я использовал в примере кода, равны или похожи на то, что мы на самом деле имеем в нашем коде.Если мы изменим max(p.last_updated) last_updated на max(p.last_updated) max_last_updated и изменим предложение WHERE на использование max_last_updated, мы получим OperationalError: misuse of aggregate: max() Мы также попытались добавить туда операторы AS без разницы.

Ответы [ 2 ]

2 голосов
/ 12 апреля 2019

Создайте подзапрос, который сначала выбирает обновленные процессы:

SELECT whatever you need FROM entries e 
LEFT OUTER JOIN process_steps p ON e.serial_number = p.serial_number
WHERE e.serial_number in (SELECT distinct serial_number from process_steps 
WHERE last_updated > "date here")
GROUP BY e.serial_number
1 голос
/ 12 апреля 2019

Вы можете сделать это с помощью having предложения:

SELECT . . .
FROM entries e LEFT JOIN
     process_steps ps
     ON e.serial_number = ps.serial_number
GROUP BY e.serial_number
HAVING MAX(ps.last_updated) > <your value here>;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...