在选择查询 sqlalchemy 中使用“case”抛出异常

Raz*_*orm 6 python postgresql sqlalchemy

我正在尝试将此 sql 查询构建到 sqlalchemy 中:

select distinct
    processed_by_user_uuid,
    sum(case when audited_result_uuid = PASSED_RESULT_UUID then 1 else 0 end) as "passed",
    sum(case when audited_result_uuid <> PASSED_RESULT_UUID then 1 else 0 end) as "failed",
    count(distinct processed_using) as "total audits"
from audit
where
    audited_at is not null
    and processed_at > [start_time]
    and processed_at < [end_time]
group by 1
Run Code Online (Sandbox Code Playgroud)

我的尝试:

query = Session.query(audit_table).with_entities(
    audit_table.c.processed_by_user_uuid,
    func.sum(
        case([audit_table.c.audited_result_uuid == PASSED_RESULT_UUID, 1], else_=0)
    ).label('passed'),
    func.sum(
        case([audit_table.c.audited_result_uuid != PASSED_RESULT_UUID, 1], else_=0)
    ).label('failed'),
    func.count(distinct(audit_table.c.processed_using)).label('total audits')
).filter(
    audit_table.c.audited_at is not None,
    audit_table.c.processed_at > start_time,
    audit_table.c.processed_at < end_time
).group_by(
    1
)
Run Code Online (Sandbox Code Playgroud)

当我尝试这个时,我得到了异常:

NotImplementedError: Operator 'getitem' is not supported on this expression
Run Code Online (Sandbox Code Playgroud)

从一些挖掘中,对这一行不满意:

func.sum(
    case([audit_table.c.audited_result_uuid == PASSED_RESULT_UUID, 1], else_=0)
).label('passed')
Run Code Online (Sandbox Code Playgroud)

van*_*van 11

您没有case(...)正确使用- 您需要将您的条件放在一个元组中,(condition, value)以便:

case([audit_table.c.audited_result_uuid == PASSED_RESULT_UUID, 1], else_=0)
Run Code Online (Sandbox Code Playgroud)

变成:

case([(audit_table.c.audited_result_uuid == PASSED_RESULT_UUID, 1)], else_=0)
Run Code Online (Sandbox Code Playgroud)

这同样适用于其他case声明。


此外,您的过滤条件audit_table.c.audited_at is not None不会导致您尝试构建的查询。该表达式将计算为booleanvalue of True,因此将生成一个真实的 WHERE子句,例如WHERE 1=1(或根本没有)。
相反,您应该使用audit_table.c.audited_at != None. PEP-8 检查会报错,但这就是它应该与 sqlalchemy 一起使用的方式。