SQLAlchemy:如何过滤日期字段?


105

这是模型:

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

我想在两个日期之间进行过滤,例如选择间隔18-30年的所有用户。

如何用SQLAlchemy实现它?

我想:

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

# means age >= 24 and age <= 27

我知道这是不正确的,但是该怎么做正确呢?

Answers:


181

实际上,除了错别字,您的查询是正确的:您的过滤器排除了所有记录:您应该更改<=for >=,反之亦然:

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

您也可以使用between

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

28
顺便说一句,'1985-01-17'您也可以使用datetime.date(1985, 1, 17)- 代替-在某些环境中可能更容易接触或使用。
tossbyte

5
@rippleslash:您是对的,理想情况下,应该使用正确的数据类型作为参数。但是,所有数据库也都知道日期的ISO 8601格式,这也恰好是字典顺序。因此,出于简单示例的原因,我通常使用ISO格式的日期-易于阅读。
面包车

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

它等于:

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

希望可以帮助你。


3

如果要获得整个期间:

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

这表示范围:1985-01-17 00 : 00-1988-01-17 23:59


危险:虽然这可能是明显一些-这仅适用于因为func.dateCAST上列从等式中删除时间 =>这确实平均范围与时间!仅当时间不在列中时,此方法才有效-您必须像这样将其CAST设置为Date,或将列设为DateTime(一旦它是DateTime或时间戳记)-通常以00:00结束(MySQL和PostgreSQL都这样做)。更通用的解决方案不是强制转换,而是将发送到的日期设置为.endOfDay(),以便您实际发送1988-01-17 23:59:59到数据库进行比较:)
jave.web
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.