상황: 한 매장의 2023년 3월 전체 주문 수와 픽업 완료 주문 수를 함께 출력한다.
BAD SQL — 기존 또는 비교 대상
SELECT
(SELECT COUNT(*)
FROM tr_ord_big AS o
WHERE o.shop_id = 'S033'
AND o.ord_dtm >= TIMESTAMP '2023-03-01'
AND o.ord_dtm < TIMESTAMP '2023-04-01') AS all_cnt,
(SELECT COUNT(*)
FROM tr_ord_big AS o
WHERE o.shop_id = 'S033'
AND o.ord_dtm >= TIMESTAMP '2023-03-01'
AND o.ord_dtm < TIMESTAMP '2023-04-01'
AND o.ord_st = 'PKUP') AS pkup_cnt;
SQL
복사
GOOD SQL — 권장 또는 대안
SELECT COUNT(*) AS all_cnt,
COUNT(*) FILTER (WHERE o.ord_st = 'PKUP') AS pkup_cnt
FROM tr_ord_big AS o
WHERE o.shop_id = 'S033'
AND o.ord_dtm >= TIMESTAMP '2023-03-01'
AND o.ord_dtm < TIMESTAMP '2023-04-01';
SQL
복사
핵심
•
집계 대상이 같고 조건만 다르면 PostgreSQL의 FILTER (WHERE ...)로 여러 집계를 한 번에 표현할 수 있다.
참고·예외
•
COUNT(CASE WHEN 조건 THEN 1 ELSE 0 END)는 ELSE 0이 NULL이 아니므로 전체 행을 세는 잘못된 작성법이다. 비교할 때는 COUNT(*) FILTER (...) 또는 NULL을 반환하는 CASE를 사용한다. 두 독립 인덱스 조회가 매우 선택적이면 BAD가 더 유리할 수도 있다.


