2010-05-28 33 views
5

Tôi có hai bảng có cột 'ngày'. Một cái giữ (tên, ngày tháng) và cái kia giữ (ngày, p1, p2). Cho một cái tên, tôi muốn sử dụng ngày trong bảng 1 để truy vấn p1 và p2 từ bảng hai; trận đấu sẽ xảy ra nếu ngày trong bảng một là trong vòng hai giây của ngày trong bảng hai.Lọc đối tượng trong vòng hai giây bằng cách sử dụng SQLAlchemy

Làm cách nào bạn có thể thực hiện việc này bằng SQLAlchemy?

Tôi đã thử (không thành công) để sử dụng between điều hành và với một điều khoản như:

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)) 

Bất kỳ suy nghĩ?

Edit: tôi đã quản lý để giải quyết vấn đề bằng cách sử dụng phương pháp sau đây:

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 

Vì vậy, việc so sánh có thể được thực hiện, nhưng tôi không chắc chắn phương pháp này là hiệu quả.

Trả lời

0

Sau một thời gian với câu hỏi này mở, phương pháp này cho đến nay là một trong tôi đã đi lên với:

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 

Nếu bạn có một ý tưởng tốt hơn, tôi sẽ chấp nhận câu trả lời của bạn.

3

Hãy để tôi giải thích lý do tại sao những gì bạn đã thử không hoạt động. SQLAlchemy chỉ là một cách thuận tiện để viết các truy vấn SQL, tất cả các truy vấn vẫn xảy ra ở phía xa. Các cột SQLAlchemy là các đối tượng đặc biệt có các phương thức __eq__, __gt__ vv được ghi đè để không trả lại là True hoặc False, nhưng các đối tượng đặc biệt khác, nhớ đối tượng nào được so sánh và có thể tạo các câu lệnh SQL thích hợp sau này. Điều tương tự là để thêm vv: Phương thức __add__, __sub__ tùy chỉnh không trả về một số hoặc một chuỗi được nối mà còn là một đối tượng, tạo ra một câu lệnh sql. Bạn có thể so sánh/thêm chúng vào chuỗi, số nguyên v.v., các cột khác, câu lệnh chọn, hàm mysql gọi etc, nhưng không phải đối với các đối tượng python đặc biệt như timedeltas. (Giản thể, và có lẽ về mặt kỹ thuật không chính xác 100%;))

Vì vậy, những gì bạn có thể làm là:

  • Tận dụng giá trị trong cơ sở dữ liệu số nguyên, ví dụ như unix timestamps. Bằng cách đó, truy vấn between của bạn sẽ hoạt động (với 2 thay vì đồng bằng)
  • Sử dụng các hàm phía cơ sở dữ liệu để chuyển đổi định dạng ngày giờ thành dấu thời gian và sau đó thực hiện so sánh.

UPDATE: Tôi đã chơi xung quanh một chút với điều đó, và bằng cách nào đó nó làm việc, thậm chí còn có một loại Interval dữ liệu. Tuy nhiên ít nhất ở đây nó không hoạt động đúng cách:

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)] 

Tôi không biết lý do tại sao người đầu tiên không thành công trên MySQL và tại sao nó trả nổi. Các lỗi SQLite dường như xảy ra vì SQLite does not have a DATETIME data type and SQLAlchemy stores it as a string.

Bạn sẽ phải chơi xung quanh với điều đó một chút, có thể bạn sẽ tìm thấy một cách hoạt động - nhưng tôi nghĩ rằng để ở thực sự dbms độc lập phương pháp số nguyên sẽ là cách khả thi duy nhất.

+0

Vấn đề về định dạng khác cho các đối tượng thời gian có thể trở thành đau đầu! – Escualo

1

Cách tiếp cận là chuyển đổi ngày thành dấu thời gian unix.

Trong một mã gần đây tôi đã sử dụng các dòng sau thành công:

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

Lưu ý, tuy nhiên, func.xxx mà chỉ đơn giản bản xxx với truy vấn như là một chuỗi, vì vậy cơ sở dữ liệu có hỗ trợ chức năng xxx. Ví dụ này là dành cho MySQL.

Các vấn đề liên quan