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