case () 사용시“Operator 'getitem'은이 표현식에서 지원되지 않습니다.”오류 해결 방법

Nov 16 2020

다음 SQL을 SQLAlchemy로 변환하려고합니다.

select t1.id, t1.field_A,
    max(case when t2.field_B = 1 then t2.field_C end) test_2_field_b_1,
    max(case when t2.field_B = 2 then t2.field_C end) test_2_field_b_2
from test_1 t1
inner join test_2 t2 on t2.field_A = t1.field_A
group by t1.id, t1.field_A

내가 가지고있는 것 :

qry = session.query(
    Test1.id_,
    Test2.field_A,
    func.max(case((Test2.field_B.__eq__(1), "Test2.field_C"))).label("test_2_field_b_1"),
    func.max(case((Test2.field_B.__eq__(2), "Test2.field_C"))).label("test_2_field_b_2"),
)
qry = qry.select_from(Test1)
qry = qry.join(Test2, Test2.field_A.__eq__(Test1.field_A))
qry = qry.group_by(Test1.id_, Test2.field_A)

하지만 다음과 같은 오류가 발생합니다.

NotImplementedError: Operator 'getitem' is not supported on this expression

라인에서 :

func.max(case((Test2.field_B.__eq__(1), "Test2.field_C"))).label("test_2_field_b_1"),

그래서 너무 많은 코드가 있다고 말하면서 전체 트레이스 백을 게시하지 않을 것입니다!

내가 어디로 잘못 가고 있습니까?

답변

2 snakecharmerb Nov 17 2020 at 01:16

case 는 when 기준 의 목록 을 첫 번째 인수로 취 하므로 적절하게 대괄호를 사용해야합니다.

sa.case([(Model.column == value)])

따라서 코드는 다음과 같아야합니다.

qry = session.query(
    Test1.id_,
    Test2.field_A,
    sa.func.max(sa.case([(Test2.field_B == 1, "Test2.field_C")])).label("test_2_field_b_1"),
    sa.func.max(sa.case([(Test2.field_B == 2, "Test2.field_C")])).label("test_2_field_b_2"),
)
qry = qry.select_from(Test1)
qry = qry.join(Test2, Test2.field_A == Test1.field_A)

oskros Nov 16 2020 at 18:21

이것은 귀하의 질문에 직접 대답하지는 않지만 과거에는 SQL 쿼리에 pyodbc 및 pandas를 사용하여 훨씬 더 많은 행운을 얻었으므로 쿼리를 번역 할 필요가 없습니다.

import pandas as pd
import pyodbc

conn = pyodbc.connect("<Insert connection string here>")
sql = """
select t1.id, t1.field_A,
    max(case when t2.field_B = 1 then t2.field_C end) test_2_field_b_1,
    max(case when t2.field_B = 2 then t2.field_C end) test_2_field_b_2
from test_1 t1
inner join test_2 t2 on t2.field_A = t1.field_A
group by t1.id, t1.field_A
"""
df = pd.read_sql(sql, conn)