从日期字段按月份和年份分组

Hou*_*run 6 python postgresql sqlalchemy

来自下表Loan_Amendment中的数据:

    ID     |     Amount     | AddDeduct | AmendDate  
-----------+----------------+-----------+------------
 LT0000160 | 1000.000000000 | 2         | 2018-02-08
 LT0000170 | 1500.00000000  | 1         | 2018-02-10
 LN0000577 | 1000.000000000 | 1         | 2018-03-20
 LN0000587 | 2000.000000000 | 2         | 2018-03-20
Run Code Online (Sandbox Code Playgroud)

我试图选择Amount具有相同年份和月份的sum字段AmendDate

因此,我尝试如下选择查询SQLALchemy

AmendObj = db.session.query(func.sum(Loan_Amendment.Amount).label('Amount'),
                            Loan_Amendment.AmendDate).\
    group_by(Loan_Amendment.AmendDate).\
    first()
Run Code Online (Sandbox Code Playgroud)

但是,从我尝试过的上述查询中,我只能按完全相同的日期(年、月和日)对AmendDate.

更新:

我的模型如下所示:

class Loan_Amendment(Object):
    ID              =   db.Column(db.String(13), primary_key=True)
    AddDeduct       =   db.Column(db.String(1))
    Amount          =   db.Column(db.Numeric(25, 9))
    AmendDate       =   db.Column(db.String(20))
Run Code Online (Sandbox Code Playgroud)

目前,我使用Flask-SQLAlchemy==2.0andSQLAlchemy==0.9.9和 DB 类型是postgresql.

我可以通过哪种方式仅按月和年从AmendDate?

Ilj*_*ilä 7

使用该date_trunc()函数将日期截断为月份精度:

month = func.date_trunc('month', Loan_Amendment.AmendDate)

AmendObj = db.session.query(func.sum(Loan_Amendment.Amount).label('Amount'),
                            month).\
    group_by(month).\
    first()
    # Did you mean all()?
Run Code Online (Sandbox Code Playgroud)

另一个不太依赖数据库的选项是使用EXTRACT()

from sqlalchemy import extract

AmendObj = db.session.query(func.sum(Loan_Amendment.Amount).label('Amount'),
                            extract('year', Loan_Amendment.AmendDate),
                            extract('month', Loan_Amendment.AmendDate)).\
    group_by(extract('year', Loan_Amendment.AmendDate),
             extract('month', Loan_Amendment.AmendDate)).\
    first()
Run Code Online (Sandbox Code Playgroud)

由于您的日期列实际上是文本,因此您首先需要进行强制转换。如果您使用的是具有ColumnElement.cast()快捷方式 1.0.7 或更高版本的 SQLAlchemy 版本,则只需

func.date_trunc('month', Loan_Amendment.AmendDate.cast(Date))
Run Code Online (Sandbox Code Playgroud)

但如果不是,那么

from sqlalchemy import cast

func.date_trunc('month', cast(Loan_Amendment.AmendDate, Date))
Run Code Online (Sandbox Code Playgroud)

当然,如果使用 EXTRACT,同样适用。


给定您的模型和数据的一个 hacky 解决方案是简单地采用包含年和月部分的子字符串并按它分组:

month = func.substr(Loan_Amendment.AmendDate, 1, 7)
Run Code Online (Sandbox Code Playgroud)