SQL[COALESCE]

oswaldeff·2022년 11월 19일
0
post-thumbnail

🖍 intro

frontend로부터 request되는 api에 대해 다수의 url query parameter 조건들을 적용해야 할때, 이를테면 drf(django rest framework)에서 상품목록을 반환하는 ListAPIView의 경우 if문과 Q객체를 통해 손쉽게 해결했었다.

from django.db.models import Q
...
class ProductListAPIView(ListAPIView)
	q = Q()

	if category:
    	q &= Q(category_value=category)
	if color:
    	q &= Q(color_value=color)
	if size:
		q &= Q(size_value=size)

	self.queryset = Product.objects.filter(q)
...

예를 들어, frontend에서 사용하는 셀렉박스에 대해 상품목록을 반환하는 API는 위와같이 category & color & size에 대한 multiple query parameters를 가지고 있기 때문에 if문을 통해 조건이 주어졌을때와 주어지지 않았을때, 필요할때만 sql의 where and or 사용한다.

이렇게 drf에서는 ORM만으로 db model에서 제공하는 Q를 통해 구현했었는데, fastapi에서 native sql을 통해 간단하게 여겨였던 query구문들이
막상 깔끔하게 구현하기가 어려웠다.

📕 function

처음에는 if문을 통해 덕지덕지 각각의 조건에 대한 query를 만들었는데 COALESCE라는 sql함수를 알게되어 하나의 query문 안에서 주어진 문제를 해결할 수 있게 되었다.

아래와 같은 query문이 주어졌을때, COALESCE function은 인자들중 NULL이 아닌 첫번째 값을 반환한다.

query = f"""
COALESCE(NULL, NULL, 2, 1)
"""

이때 query문에서 COALESCE는 2를 반환한다.

💻 solve

다시 주어진 문제로 돌아와서,

api.domain.com/product/list

api.domain.com/product/list?category=신발?color=분홍?size=L

와 같이 category, color, size의 multiple query parameters이 주어졌을 경우, 모든 경우의 수들에 일일이 대응되는 query문들을 작성할게 아니라
하나의 query문안에서 해결하는게 좋은 방향이라고 생각되어 아래와 같이 작성하였다.

def select_product_list(category, color, size):
	query = """
    	SELECT
        	*
        FROM
        	product
        WHERE
        	category_value = COALESCE('{category}', category_value)
            AND color_value = COALESCE('{color}', color_value)
            AND size_value = COALESCE('{size}', size_value)
    """.replace("'NULL'", "NULL")
    return query

단, 여기서 parameter들이 주어지지 않을때의 category & color & size의 default값은 'NULL'이다.

category가 주어지지 않을 경우, 기존 category_value coulumn에 대해
WHERE 1=1 구문이 형성되고 특정 카테고리에 대한 조건이 아닌 모든 카테고리에 대한 데이터들이 반환된다.

color와 size 역시 동일한 구문을 통해 적용되며 이 세가지 query parameter들은 AND구문으로 묶여 다중조건으로서 작용한다.


2022.11.28
COALESCE는 django의 Q()를 어떻게 raw query로 옮겨올까 생각하며 구글링하다 알게된 문법이었는데, 단순 기능구현이라는 관점에서는 사용해볼 수 있는 방법이지만 프로덕션 레벨에서는 사용하기에 부하를 일으키는 문법이라는것을 피드백을 통해 알게되었다.

다시금 생각해보니 filtering parameter들에 대해 백단 서버에서 분기점을 태움으로써 실제로 정말 filtering이 필요할때만 sql서버에 질의되는게 당연하다는 생각이 들었다.
즉 sql서버에서 항상 COALESCE의 연산을 감당하게 하는것이 아니라 필요할때만 sql자원을 사용하는것이 효율적이고 트래픽이 다수존재할때는 서버자원을 고려할 수 있는 것이다.

0개의 댓글