Объекты фильтра в течение двух секунд после того использовали SQLAlchemy

У меня есть две таблицы со столбцом 'дата'. Каждый содержит (имя, дата) и другие хранения (дата, p1, p2). Данный имя, я хочу использовать дату в таблице 1 для запросов p1 и p2 от таблицы два; соответствие должно произойти, если дата в таблице каждый в течение двух секунд после даты в таблице два.

Как можно выполнить это использование SQLAlchemy?

Я попытался (неудачно) использовать between оператор и с пунктом как:

td = datetime.timedelta(seconds=2)
q = session.query(table1, table2).filter(table1.name=='my_name').\
    filter(between(table1.date, table2.date - td, table2.date + td))

Какие-либо мысли?

Править: Мне удалось решить проблему с помощью следующего подхода:

from sqlalchemy.sql import between
import datetime
# [all other relevant imports]

td = datetime.timedelta(seconds=2)
t1_entry = session.query(table_1).filter(table_1.name == 'the_name').first()
if t1_entry is not None:
 tmin = t1_entry.date - td
 tmax = t1_entry.date + td
 t2_entry = session.query(table_2).filter(between(table_2.date, tmin, tmax)).first()
 return (t1_entry, t2_entry)
return None

Таким образом, сравнение может быть сделано, но я не уверен, что подход эффективен.

5
задан Escualo 29 May 2010 в 00:06
поделиться

2 ответа

Через некоторое время, когда этот вопрос открыт, я пришел к такому подходу:

from sqlalchemy.sql import between
import datetime
# [all other relevant imports]

td = datetime.timedelta(seconds=2)
t1_entry = session.query(table_1).filter(table_1.name == 'the_name').first()
if t1_entry is not None:
 tmin = t1_entry.date - td
 tmax = t1_entry.date + td
 t2_entry = session.query(table_2).filter(between(table_2.date, tmin, tmax)).first()
 return (t1_entry, t2_entry)
return None

Если у вас есть идея получше, я приму ваш ответ.

0
ответ дан 15 December 2019 в 00:52
поделиться

Позвольте мне сначала объяснить, почему то, что вы попробовали, не работает. SQLAlchemy - это просто удобный способ написания SQL-запросов, все запросы, тем не менее, происходят на удаленной стороне. Колонки SQLAlchemy - это специальные объекты, чьи методы __eq__, __gt__ и т.д. переписаны, чтобы возвращать не True или False, а другие специальные объекты, которые помнят, с каким объектом они сравнивались, и могут генерировать соответствующие SQL-запросы позже. То же самое касается добавления и т.д: Пользовательский метод __add__, __sub__ возвращает не число или конкатенированную строку, а такой объект, который генерирует sql-запрос. Вы можете сравнивать / добавлять их к строкам, целым числам и т.д., другим столбцам, операторам select, вызовам функций mysql и т.д., но не к специальным объектам python, таким как timedeltas. (Упрощенно, и, возможно, технически не на 100% правильно ;) )

Итак, что вы можете сделать:

  • Сделать значения в базе данных целыми числами, например, временными метками unix. Таким образом, ваш запрос between будет работать (с 2 вместо дельты)
  • Используйте функции на стороне базы данных для преобразования даты в формате datetime в unix timestamp, а затем выполните сравнение.

UPDATE: Я немного поигрался с этим, и как-то это работает, есть даже тип данных Interval . Однако по крайней мере здесь он не работает должным образом:

MySQL:

>>> db.session.execute(db.select([User.date_joined, User.date_joined + timedelta(seconds=2)], limit=1)).fetchall()
[(datetime.datetime(2009, 7, 10, 20, 47, 33), 20090710204733.0)]
>>> db.session.execute(db.select([User.date_joined, User.date_joined + 2], limit=1)).fetchall()
[(datetime.datetime(2009, 7, 10, 20, 47, 33), 20090710204735.0)]
>>> db.session.execute(db.select([User.date_joined+0, User.date_joined + 2], limit=1)).fetchall()
[(20090710204733.0, 20090710204735.0)]

SQLite:

>>> db.session.execute(db.select([User.date_joined, User.date_joined + timedelta(seconds=2)], limit=1)).fetchall()
TypeError: expected string or buffer
>>> db.session.execute(db.select([User.date_joined, User.date_joined + 2], limit=1)).fetchall()
[(datetime.datetime(2010, 5, 28, 23, 8, 22, 476708), 2012)]
>>> db.session.execute(db.select([User.date_joined+0, User.date_joined + 2], limit=1)).fetchall()
[(2010, 2012)]

Я не знаю, почему первый вариант не работает в MySQL и почему он возвращает floats. Ошибки SQLite, похоже, происходят потому, что SQLite не имеет типа данных DATETIME, а SQLAlchemy хранит его как строку.

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

3
ответ дан 15 December 2019 в 00:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: