SQLAlchemy:如何过滤日期字段?

Vit*_*mar 93 python sql database orm sqlalchemy

这是模型:

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

我想在两个日期之间进行过滤,例如选择间隔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
Run Code Online (Sandbox Code Playgroud)

我知道这不正确,但怎么做正确?

提前致谢!

van*_*van 158

事实上,您的查询是正确的,除了错字:您的过滤器排除了所有记录:您应该更改<=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')
Run Code Online (Sandbox Code Playgroud)

你也可以使用between:

qry = DBSession.query(User).filter(User.birthday.between('1985-01-17', '1988-01-17'))
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,你也可以使用`datetime.date(1985,1,17)`而不是''1985-01-17'` - 在某些环境中可能更容易使用或使用. (23认同)
  • @rippleslash:你是对的,理想情况下应该使用适当的参数数据类型.但是,所有数据库也理解日期的ISO 8601格式,这也恰好是字典顺序.出于这个原因,对于简单的例子,我通常使用ISO格式的日期 - 更容易阅读. (4认同)

小智 7

如果你想获得整个时期:

    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'))
Run Code Online (Sandbox Code Playgroud)

这意味着范围:1985-01-17 00:00 - 1988-01-17 23:59

  • **危险:**虽然这对某些人来说可能是显而易见的 - 这只有效,因为`func.date`在列上进行*CAST*,**从方程中删除时间** =&gt;这*不*意味着范围与**时间!**这仅在时间不在列中时才有效 - 您必须像这样将其转换为日期,或者将列设置为日期,一旦它是日期时间或时间戳 - 通常以 00:00 结束(MySQL &amp; PostgreSQL 就是这样做的)。更通用的解决方案不是进行强制转换,而是设置要发送到 .endOfDay() 的日期,这样您实际上将 `1988-01-17 23:59:59` 发送到数据库比较:) (3认同)

ato*_*ool 5

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()
Run Code Online (Sandbox Code Playgroud)

它等于:

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

希望能帮到你。