SQLAlchemy 그룹별 가장 최신값

IOVEIT·2023년 9월 28일
0

같은 상품끼리 묶어서 가장 최신 것을 찾아내는 SQLAlchemy ORM 코드다. SQL 쿼리로는 쉬운데, sqlalchemy ORM에선 좀 다르게 처리된다. 다음과 같다.

✔ PRODUCT_HISTORY_TB

>> before
id | name        | dealer  | price | changed_at   
1  | iphone14    | a inc   | 100   | 2023-01-01
1  | iphone14    | b corp  | 101   | 2023-01-03
1  | iphone14    | c inc   | 102   | 2023-01-02
2  | galaxy s23  | a inc   | 99    | 2023-02-20
2  | galaxy s23  | d corp  | 98    | 2023-02-21
2  | galaxy s23  | a inc   | 97    | 2023-02-22
3  | lg gram     | b corp  | 200   | 2023-05-01

>> after
1  | iphone14    | b corp  | 101   | 2023-01-03
2  | galaxy s23  | a inc   | 97    | 2023-02-22
3  | lg gram     | b corp  | 200   | 2023-05-01

✔ sqlalchemy 서브쿼리

subquery = session.query(
               func.rank().over(
                   order_by=PRODUCT_HISTORY_TB.changed_at.desc(),
                   partition_by=PRODUCT_HISTORY_TB.id).label('rnk'), 
               PRODUCT_HISTORY_TB
           ).subquery()

id를 partition by로 그룹화하고 날짜 역순으로 정렬하여, 그룹 내에서 순서대로 순위(1, 2, 3)를 매긴다. 가장 최근 날짜에 해당하는 행의 첫번째 컬럼명은 rnk이고, 값에는 1이 들어간다.

✔ sqlalchemy 최종쿼리

예시1 : 첫번째 컬럼은 rnk가 되고, 값이 '1'로 나온다.
result = session.query(PRODUCT_HISTORY_TB).filter(subquery.c.rnk == 1).all()

예시2 : 첫번째 컬럼에 순위값 '1'이 안 나오게 하려면, 컬럼을 직접 입력한다.
result = session.query(
            subquery.c.id,
            subquery.c.name,
            subquery.c.dealer,
            subquery.c.price,
            subquery.c.changed_at
         ).filter(subquery.c.rnk == 1).all()


서브쿼리 내에 특정 컬럼을 참조하려면, 'subquery.c.컬럼명'을 사용해야 한다. 즉 ".c"가 들어가야 한다. "ㅤ"

profile
EnCoCookLand

0개의 댓글