在SQLAlchemy查询中使用多个having语句

1 投票
1 回答
2222 浏览
提问于 2025-04-17 23:19

SQLAlchemy中的操作顺序是什么样的?理想的回答应该提供一些普遍适用的规则,而不是针对特定例子的解决方案。

我问这个问题的原因是这样的。我正在从一个SQLite3数据库中的多个表构建一个数据集。我的查询大概是这样的:

query = session.query( Customer, Application, Income, Spending ).\
join(
    <USER-APPLICATION JOIN>
).\
join(
    <USER-INCOME JOIN>
).\
join(
    <USER-SPENDING JOIN>
).\
group_by(
    User.id,
    Application.date,
)

现在,我不想从这些表中提取所有数据,所以我在查询上加了一些过滤条件。例如:

query = query.\
filter( 
    Income.date <= Application.date
).\
having(
    or_(
        and_(
            func.max(Spending.date) <= Application.date,
            Spending.date == func.max(Spending.date)
        ),
        and_(
            func.max(Spending.date) > Application.date,
            Spending.date < Application.date
        ),
        and_(
            func.min(Spending.date) > Application.date,
            Spending.date == func.min(Spending.date)
        )
    )
).\
having(
    Spending.date == func.max(Spending.date),
    Income.date == func.max(Income.date)
)

但是,这些过滤条件是相互依赖的,只有当第一个过滤条件在第二个之前应用时,上面的代码才能达到我想要的效果。

那么,这段代码的行为是我想要的吗?此外,这种行为是否依赖于我使用的数据库(因为我可能将来想要更换数据库)?

1 个回答

2

在这种情况下:

query.filter(...).having(...)

...在filter()里面的内容会变成一个WHERE子句,而having()里面的内容会变成HAVING子句。

WHERE子句是在分组之前对行进行筛选的,而HAVING子句是对分组后的结果进行筛选。因此,HAVING子句只会作用于那些已经通过了WHERE子句筛选的行。

所以,你的代码会按照你写的方式正常运行。

撰写回答