고객별 주문 합계를 구할 때는 GROUP BY를 쓰면 돼요. 그런데 주문 한 건의 금액과 그 고객의 전체 주문 금액을 나란히 보고 싶다면 어떨까요?
이번에는 행을 합치지 않고 합계만 옆에 붙여 보려고 해요. 예제는 직접 만든 데이터이며 SQLite에서 실행했어요.
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer TEXT NOT NULL,
amount INTEGER NOT NULL
);
INSERT INTO orders VALUES
(1, '가온', 12000),
(2, '나래', 8000),
(3, '가온', 5000);
가온은 두 번, 나래는 한 번 주문했어요. 고객별로 묶으면 결과는 두 행이 됩니다.
SELECT customer, SUM(amount) AS total
FROM orders
GROUP BY customer
ORDER BY customer;
| customer | total |
|---|---|
| 가온 | 17000 |
| 나래 | 8000 |
전체 금액을 비교할 때는 이 결과로 충분해요. 다만 개별 주문 번호와 금액은 보이지 않죠.
SELECT
order_id,
customer,
amount,
SUM(amount) OVER (PARTITION BY customer) AS customer_total
FROM orders
ORDER BY order_id;
| order_id | customer | amount | customer_total |
|---|---|---|---|
| 1 | 가온 | 12000 | 17000 |
| 2 | 나래 | 8000 | 8000 |
| 3 | 가온 | 5000 | 17000 |
PARTITION BY customer는 계산할 범위를 고객별로 나눠 줘요. 같은 고객의 금액을 더한 뒤 각 주문 행 옆에 그 결과를 보여 줍니다. 이런 방식으로 계산하는 함수를 윈도우 함수라고 해요.
이 쿼리에서는 원래 주문 세 행이 그대로 남아요. 가온의 합계가 두 번 나오는 것도 중복 오류가 아니라, 두 주문에 같은 고객 합계가 붙은 결과예요.
위 결과의 customer_total을 모두 더하면 42000이 돼요. 실제 전체 주문 금액인 25000과 다르죠. 가온의 17000이 두 번 더해졌기 때문이에요.
고객별 합계만 필요한지, 주문 내역과 함께 볼 것인지에 따라 결과의 한 행이 무엇을 뜻하는지 먼저 정하면 좋아요.
또 마지막의 ORDER BY order_id는 출력 순서를 정해요. OVER 안에 ORDER BY를 추가하는 것은 계산 범위에도 영향을 줄 수 있으므로, 보기 좋게 정렬하려고 무심코 넣지는 않는 편이 좋아요. 이번 예제에서는 고객 전체 합계를 구하려고 OVER 안의 정렬을 생략했어요.