같은 상품끼리 묶어서 가장 최신 것을 찾아내는 SQLAlchemy ORM 코드다. SQL 쿼리로는 쉬운데, sqlalchemy ORM에선 좀 다르게 처리된다. 다음과 같다.
>> 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
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이 들어간다.
예시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"가 들어가야 한다. "ㅤ"