首页 > 解决方案 > Psycopg2 在查询中使用 CASE 语句时无法调整类型“BinaryExpression”

问题描述

我有下一个查询:

sub_qry = self.session.query(
    TableA.currency,
    func.sum(func.case([(TableB.status_id == EStatus.REPORTED.value, 1)], else_=0)).label('status')
) \
    .filter_by(period_id=period_id) \
    .outerjoin(TableB) \
    .group_by(TableA.currency) \
    .subquery()
result = self.session.query(func.count(sub_qry.c.status)).filter(sub_qry.c.status != 1).first()

但它因错误而崩溃:

(psycopg2.ProgrammingError) can't adapt type 'BinaryExpression'
[SQL: SELECT count(anon_1.status) AS count_1 
FROM (SELECT table_a.currency AS currency, sum(case(%(case_1)s)) AS status 
FROM table_a LEFT OUTER JOIN table_b ON table_a.id = table_b.table_a_id 
WHERE table_a.period_id = %(period_id_1)s GROUP BY table_a.currency) AS anon_1 
WHERE anon_1.status != %(status_1)s 
 LIMIT %(param_1)s]
[parameters: {'case_1': [(<sqlalchemy.sql.elements.BinaryExpression object at 0x0000022FC0F42700>, 1)], 'period_id_1': 4, 'status_1': 1, 'param_1': 1}]
(Background on this error at: http://sqlalche.me/e/13/f405)

我究竟做错了什么?我在网上查了很多样品,似乎一切都很好。

添加:
有效的 SQL 版本:

select count(r.status)
    from (
        select a.currency, SUM(CASE WHEN b.status_id = 2 THEN 1 else 0 END) as status from table_b b
            right outer join table_a a on a.id = b.table_a_id
            where a.period_id = 4
            group a.currency
    ) r
    where r.status != 1

标签: pythonsqlalchemypsycopg2

解决方案


我发现了我的错误:调用sqlalchemy.func.case()而不是sqlalchemy.case().
这一点很重要!SQLAlchemy只会在第二种情况下生成正确的 SQL 查询。

PS这是一个微不足道的错误,但如果有人遇到同样的问题,我决定将其保存在这里。


推荐阅读