Python sqlalchemy查询日期时间间隔

Python sqlalchemy查询日期时间间隔,python,flask-sqlalchemy,Python,Flask Sqlalchemy,我用炼金术定义了一张桌子。显示在下面 class Notes(db.Model): id = db.Column(db.Integer, primary_key=True) notes = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) added_at = db.Column(db.DateTi

我用炼金术定义了一张桌子。显示在下面

class Notes(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    notes = db.Column(db.Text, nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    added_at = db.Column(db.DateTime, default=db.func.now())

@staticmethod
def newest(num):
    return Notes.query.order_by(desc(Notes.added_at)).limit(num)
我试图编写一个查询来替换已经存在的直接查询,如下所示

select notes,user,added_at from notes where added_at >= now() - INTERVAL 8 HOUR;
然而,根据我能找到的文档,我无法找到一种方法来做同样的事情。我能够进行更简单的查询,但我正在努力重新创建sql本身非常简单的功能


我非常愿意阅读一些关于它的文档,但我也无法准确地确定这一点。你能提供的任何方向都会很棒

您可以尝试以下方法

Notes.query.order_by(desc(Notes.added_at)).filter(
    Notes.added_at >= text('NOW() - INTERVAL 8 HOURS').limit(num)
由于我只使用纯sqlalchemy,因此我使用以下语法对此进行了测试:

>>> from sqlalchemy import text
>>> # s is a standard sqlalchemy session created from elsewhere.
>>> print s.query(Notes).order_by(desc(Notes.added_at)).filter(
...     Notes.added_at >= text('NOW() - INTERVAL 8 HOURS'))
SELECT notes.id AS notes_id, notes.notes AS notes_notes, notes.added_at AS notes_added_at 
FROM notes 
WHERE notes.added_at >= NOW() - INTERVAL 8 HOURS ORDER BY notes.added_at DESC
对该部分使用
text
的原因很简单,因为
NOW()
INTERVAL
在所有sql实现中的用法并不一致(某些实现需要使用
DATEADD
来执行datetime算法,虽然sqlalchemy确实支持
Interval
类型,但它并没有很好的文档记录,而且在我的简短测试中,它实际上并没有做您需要的事情(使用示例from,用于sqlite和MySQL)。如果您打算将SQL后端用作有序(但不是哑的)数据存储,您可以从Python中构造实际的查询,可能如下所示:

q = s.query(Notes).order_by(desc(Notes.added_at)).filter(
    Notes.added_at >= (datetime.utcnow() - timedelta(3600 * 8))
)
有些人不喜欢这一点,因为有些数据库(如postgresql)比Python更好地处理日期时间(例如,timedelta不知道闰年)。

也可以尝试

from sqlalchemy import func, text

@staticmethod
def newest(num):
    return Notes.query.filter(Notes.added_at >= (func.date_sub(func.now(),  text('INTERVAL  8 HOUR')).order_by(desc(Notes.added_at)).limit(num)


我总是使用Python的
datetime
库获取“现在”和“8小时前”,然后使用datetime进行筛选:

from datetime import datetime, timedelta

now = datetime.now()
eight_hours_ago = now - timedelta(hours=8)

Notes.query.filter(Notes.added_at > eight_hours_ago).filter(Notes.added_at < now).all()
从datetime导入datetime,timedelta
now=datetime.now()
八小时前=现在-时间增量(小时=8)
Notes.query.filter(Notes.added_在>八小时前)。filter(Notes.added_在<现在)。all()

以下各项也应适用:

from sqlalchemy import func
from sqlalchemy.dialects.postgresql import INTERVAL
from sqlalchemy.sql.functions import concat

Notes.query\
    .filter(
        Notes.added_at >= (func.now() - func.cast(concat(8, ' HOURS'), INTERVAL))
    )\
    .limit(num)

它有一个很好的特性,
8
可以替换为数据库中的值,例如,如果您加入另一个具有动态间隔的表。我也给出了这个答案。

我看到了这个可能的重复,但是它没有足够的信息来重新创建我试图实现的间隔函数。谢谢ough.date_sub不是postgres函数:(是的,它是一个MySQL函数,可以使用
NOW()-“8小时”::INTERVAL
from sqlalchemy import func
from sqlalchemy.dialects.postgresql import INTERVAL
from sqlalchemy.sql.functions import concat

Notes.query\
    .filter(
        Notes.added_at >= (func.now() - func.cast(concat(8, ' HOURS'), INTERVAL))
    )\
    .limit(num)