2010-05-28 47 views
5

我有兩個表'日期'列。一個持有(姓名,日期),另一個持有(日期,p1,p2)。給定一個名字,我想用表1中的日期從表2中查詢p1和p2;如果表1中的日期在表2中的日期之內,則應該發生匹配。使用SQLAlchemy在兩秒鐘內過濾對象

如何使用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 

這樣的比較可以做到的,但我不知道這種方法是有效的。

回答

0

一段時間後,這個問題開放,這種方法至今是一個我想出來的:

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 

如果你有更好的想法,我會接受你的答案。

3

讓我先解釋一下爲什麼你所嘗試的不起作用。 SQLAlchemy只是編寫SQL查詢的一種便捷方式,所有的查詢仍然發生在遠程端。 SQLAlchemy的列是特殊的對象,它們的__eq____gt__等方法覆蓋返回不TrueFalse,但其他特殊對象,記住什麼是他們進行了比較,後來又可以生成相應的SQL語句的對象。同樣是添加等:自定義__add__,__sub__方法不會返回一個數字或連接的字符串,但也會返回一個生成一個sql語句的對象。你可以比較/添加它們到字符串,整數等,其他列,選擇語句,mysql函數調用等,但不是特殊的python對象,如timedeltas。(簡體,而且很可能在技術上不是100%正確;))

所以你可以做的是:

  • 在數據庫中整數值,例如UNIX時間戳。這樣你的between查詢將工作(與2,而不是增量)
  • 使用數據庫端函數將日期時間格式日期轉換爲unix時間戳,然後進行比較。

更新:我周圍有點玩過了,並且莫名其妙它的工作,甚至有是一個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的第一個失敗,爲什麼它返回浮動。 SQLite錯誤似乎發生,因爲SQLite does not have a DATETIME data type and SQLAlchemy stores it as a string

你必須玩的是一點點,也許你會發現一個可行的辦法 - 但我想留真DBMS獨立的整數方法將是唯一可行的辦法。

+0

此問題的時間對象的不同格式可能會成爲頭痛! – Escualo 2010-05-29 00:09:26

1

該方法是將日期轉換爲unix時間戳。

在最近的代碼我用下面的行成功:

from sqlalchemy.sql import func 
... 
q = q.join(q2, func.abs(func.unix_timestamp(rssi1.datetime)-func.unix_timestamp(q2.c.datetime)) <=2) 

但是請注意,這func.xxx簡單的拷貝XXX的查詢作爲一個字符串,所以數據庫必須支持的功能XXX。這個例子是針對MySQL的。