SQLAlchemy:如何过滤日期字段?

Posted

技术标签:

【中文标题】SQLAlchemy:如何过滤日期字段?【英文标题】:SQLAlchemy: how to filter date field? 【发布时间】:2012-02-12 06:59:29 【问题描述】:

这是型号:

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

我知道这是不正确的,但是如何正确呢?

【问题讨论】:

【参考方案1】:

事实上,您的查询是正确的,除了错字:您的过滤器排除了所有记录:您应该将&lt;= 更改为&gt;=,反之亦然:

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

【讨论】:

顺便说一句,您也可以使用 datetime.date(1985, 1, 17) 而不是 '1985-01-17' - 在某些环境中可能更容易使用或使用。 @rippleslash:你是对的,理想情况下应该使用正确的数据类型作为参数。然而,所有数据库也理解日期的 ISO 8601 格式,这也恰好是字典顺序。出于这个原因,对于简单的示例,我通常使用 ISO 格式的日期 - 更易于阅读。 中间示例中的@van 是否包含日期? @rohitwtbs:sqlalchemy 将简单地转换为 BETWEEN 运算符的数据库实现,因此答案将取决于 RDBMS。但我相信它在所有现代 RDBMS 中都具有包容性【参考方案2】:

如果你想得到整个时期:

    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.date删除的列上执行 CAST等式中的时间 => 这确实 NOT 表示 时间的范围! 这仅在时间不在列中时有效 - 您必须将其转换为 Date像这样,或者创建列日期,一旦它是日期时间或时间戳 - 它通常以 00:00 结束(mysql 和 PostgreSQL 都这样做)。更通用的解决方案不是强制转换,而是将您发送到它的日期设置为 .endOfDay() 以便您实际上将1988-01-17 23:59:59 发送到数据库比较:)【参考方案3】:
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

希望能帮到你。

【讨论】:

【参考方案4】:

这是一个与最新的Flask 版本一起使用并使用flask-marshmallow 的版本。

from datetime import date, timedelta

from flask import jsonify

from app import db, ma
from app.models import User

from . import main

class UserSchema(ma.Schema):
    class Meta:
        fields = ('forename', 'surname', 'birthday', ...)


@main.route('/', methods=('GET',))
def get_users():

    start_range = date.today() + timedelta(years=-30)
    end_range = date.today() + timedelta(years=-18)

    users = db.session.query(User).filter(User.birthday.between(start_range, end_range)).all()

    users_schema = UserSchema(many=True)

    return jsonify(users_schema.dump(users))     

【讨论】:

我觉得你打错了date.today() + timedelta(years=-18)应该叫end_range

以上是关于SQLAlchemy:如何过滤日期字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 sqlalchemy 中的两列进行过滤

如何将自动过滤器添加到与 SQLAlchemy 的关系中?

在 Flask-SQLAlchemy 模型上使用函数查询会给出 BaseQuery object is not callable 错误

SQLAlchemy,如何将混合表达式设置为“理解”日期时间?

在 SQLAlchemy 中以特定格式按日期分组

在 graphene-sqlalchemy 查询中按 id 过滤