SQLAlchemy: làm thế nào để lọc trường ngày?


105

Đây là mô hình:

class User(Base):
    ...
    birthday = Column(Date, index=True)   #in database it's like '1987-01-17'
    ...

Tôi muốn lọc giữa hai ngày, chẳng hạn để chọn tất cả người dùng trong khoảng 18-30 năm.

Làm thế nào để triển khai nó với SQLAlchemy?

Tôi nghĩ về:

query = DBSession.query(User).filter(
    and_(User.birthday >= '1988-01-17', User.birthday <= '1985-01-17')
) 

# means age >= 24 and age <= 27

Tôi biết điều này là không chính xác, nhưng làm thế nào để làm đúng?

Câu trả lời:


181

Trên thực tế, truy vấn của bạn đúng ngoại trừ lỗi đánh máy: bộ lọc của bạn đang loại trừ tất cả các bản ghi: bạn nên thay đổi <=for >=và ngược lại:

qry = DBSession.query(User).filter(
        and_(User.birthday <= '1988-01-17', User.birthday >= '1985-01-17'))
# or same:
qry = DBSession.query(User).filter(User.birthday <= '1988-01-17').\
        filter(User.birthday >= '1985-01-17')

Ngoài ra bạn có thể sử dụng between:

qry = DBSession.query(User).filter(User.birthday.between('1985-01-17', '1988-01-17'))

28
Thay vào đó '1985-01-17', bạn cũng có thể sử dụng Btw datetime.date(1985, 1, 17)- có thể dễ sử dụng hoặc làm việc hơn trong một số môi trường.
tossbyte

5
@rippleslash: bạn nói đúng, và lý tưởng nhất là người ta nên sử dụng kiểu dữ liệu thích hợp cho các tham số. Tuy nhiên, tất cả các cơ sở dữ liệu cũng hiểu định dạng ISO 8601 cho ngày tháng, đây cũng là thứ tự từ vựng. Vì lý do này cho các ví dụ đơn giản, tôi thường sử dụng ngày tháng được định dạng ISO - dễ đọc hơn.
van

4
from app import SQLAlchemyDB as db

Chance.query.filter(Chance.repo_id==repo_id, 
                    Chance.status=="1", 
                    db.func.date(Chance.apply_time)<=end, 
                    db.func.date(Chance.apply_time)>=start).count()

nó bằng:

select
   count(id)
from
   Chance
where
   repo_id=:repo_id 
   and status='1'
   and date(apple_time) <= end
   and date(apple_time) >= start

mong muốn có thể giúp bạn.


3

nếu bạn muốn có toàn bộ thời gian:

    from sqlalchemy import and_, func

    query = DBSession.query(User).filter(and_(func.date(User.birthday) >= '1985-01-17'),\
                                              func.date(User.birthday) <= '1988-01-17'))

Đó là phương tiện phạm vi: 1985/01/17 00:00 - 1988/01/17 23:59


NGUY HIỂM: mặc dù điều này có thể rõ ràng với một số người - điều này CHỈ hoạt động vì func.dateCAST trên cột loại bỏ thời gian khỏi phương trình => điều này KHÔNG có nghĩa là phạm vi với thời gian! Điều này chỉ hoạt động khi thời gian KHÔNG có trong cột - bạn phải ĐÚC nó thành Ngày như thế này, hoặc tạo cột Ngày, khi đó là DateTime hoặc dấu thời gian - nó thường kết thúc bằng 00:00 (cả MySQL và PostgreSQL đều làm điều này). Giải pháp chung chung hơn không phải là truyền, mà là đặt ngày bạn gửi đến .endOfDay () để bạn thực sự gửi 1988-01-17 23:59:59đến cơ sở dữ liệu so sánh :)
jave.web
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.