他們是否有任何簡單(快速)的方式來獲取表並找到距離SQLAlchemy中給定dateTime最近的日期?在大多數情況下,增量將在給定的日期和表中的日期之間變成秒。SQLAlchemy最近的日期時間
日期列是主鍵
編輯: 我使用SQLite
他們是否有任何簡單(快速)的方式來獲取表並找到距離SQLAlchemy中給定dateTime最近的日期?在大多數情況下,增量將在給定的日期和表中的日期之間變成秒。SQLAlchemy最近的日期時間
日期列是主鍵
編輯: 我使用SQLite
類似的東西既然是主鍵的簡單的「排序DIFF上升,取第1行」可能不是最快的,但簡單的解決方案。一種快速和骯髒的方式可能是獲取大於和小於給定日期時間的聯合,按升序和降序排序並限於第一行,然後從第二行中選擇具有較小差異的聯合。例如使用PostgreSQL作爲後端,並用一年的時間戳記與12S分辨率的測試表:
sopython=> create table testi (key timestamp without time zone primary key);
CREATE TABLE
sopython=> insert into testi
select *
from generate_series(now() at time zone 'utc' - '1 year'::interval,
now() at time zone 'utc',
'12 seconds'::interval);
INSERT 0 2628001
和Python的:
In [29]: from sqlalchemy import union_all, case
In [30]: from sqlalchemy.orm import aliased
In [31]: the_time = datetime(2016, 5, 5, 10, 45, 55)
創建取最接近值工會,包裹在子查詢一個SELECT語句,以便它例如,也可以在SQLite中工作。
In [32]: greater = session.query(Testi).filter(Testi.key > the_time).\
...: order_by(Testi.key.asc()).limit(1).subquery().select()
In [33]: lesser = session.query(Testi).filter(Testi.key <= the_time).\
...: order_by(Testi.key.desc()).limit(1).subquery().select()
In [34]: the_union = union_all(lesser, greater).alias()
別名模型到工會
In [35]: testi_alias = aliased(Testi, the_union)
的結果從給定的日期時間
In [36]: the_diff = testi_alias.key - the_time
或SQLite中
In [36]: the_diff = func.julianday(testi_alias.key) - func.julianday(the_time)
取計算的差越接近的2 se的怪異度是在Postgresql中間隔的getting the absolute value。其他DB需要不同的解決方案進行差值計算並取絕對值。用SQLite只需func.abs(the_diff)
。
In [37]: session.query(testi_alias).\
...: order_by(case([(the_diff < timedelta(0), -the_diff)],
...: else_=the_diff)).\
...: first()
Out[37]: <sqlalchemy.ext.automap.testi at 0x7f096f837828>
In [38]: _.key
Out[38]: datetime.datetime(2016, 5, 5, 10, 45, 54, 855799)
雖然只是DIFF訂購和限制的簡單的解決方案在某些800毫秒跑這臺機器上,上面的查詢完成約70-100ms。如果您將數據翻倍,那麼簡單的解決方案 - 依賴於seq掃描 - 也是雙倍的。
工會從表中尋找這兩個值:
In [14]: session.query(testi_alias.key).all()
Out[14]:
[(datetime.datetime(2016, 5, 5, 10, 45, 54, 855799)),
(datetime.datetime(2016, 5, 5, 10, 46, 6, 855799))]
最後,你可以在一個通用的功能包了這一切:
def get_closest(session, cls, col, the_time):
greater = session.query(cls).filter(col > the_time).\
order_by(col.asc()).limit(1).subquery().select()
lesser = session.query(cls).filter(col <= the_time).\
order_by(col.desc()).limit(1).subquery().select()
the_union = union_all(lesser, greater).alias()
the_alias = aliased(cls, the_union)
the_diff = getattr(the_alias, col.name) - the_time
abs_diff = case([(the_diff < timedelta(0), -the_diff)],
else_=the_diff)
return session.query(the_alias).\
order_by(abs_diff.asc()).\
first()
get_closest(session, Testi, Testi.key, the_time)
是使用select * from表where datetime> your_date_time的限制1; select * from table where datetime
Timo
我會得到該行還是時間值? – Timo
2選擇是解決方案背後的想法,但不是完整的解決方案。請注意,如果最小差異爲0,那麼特定的查詢將不會返回正確的結果,因爲這兩個查詢都不相等。您可以調整查詢以返回任一個。 –