오늘은 좀 더 특이하지만 중요한 주제로 들어가 볼게. 바로 GREATEST()랑 LEAST() 함수야. 여러 컬럼에서 최대값, 최소값을 어떻게 찾는지, 그리고 NULL이 이 함수들에 어떤 영향을 주는지 알게 될 거야.
혹시 인생에서 제일 중요한 걸 찾아본 적 있지? (사랑, 꿈의 직장, 아니면 최고의 피자 레시피 같은 거!) 그럼 GREATEST()랑 LEAST() 함수가 왜 필요한지 바로 감이 올 거야. 이 함수들은 어떤 것들 중에서 제일 크거나 작은 값을 찾아주는 거야. 피자 대신 숫자, 날짜, 문자열, 그리고 PostgreSQL의 다른 데이터랑 놀아주는 거지.
GREATEST()
GREATEST()는 넘겨준 값들 중에서 제일 큰 값을 돌려줘.
문법:
GREATEST(value1, value2, ..., valueN)
LEAST()
LEAST()는 반대로 제일 작은 값을 찾아줘.
문법:
LEAST(value1, value2, ..., valueN)
예시:
예를 들어 students_scores라는 테이블이 있고, 거기엔 학생들의 세 번 시험 점수가 저장돼 있다고 해보자:
| student_id | exam_1 | exam_2 | exam_3 |
|---|---|---|---|
| 1 | 85 | 90 | 82 |
| 2 | NULL | 76 | 89 |
| 3 | 94 | NULL | 88 |
GREATEST()랑 LEAST()를 써보면:
SELECT
student_id,
GREATEST(exam_1, exam_2, exam_3) AS highest_score,
LEAST(exam_1, exam_2, exam_3) AS lowest_score
FROM students_scores;
결과:
| student_id | highest_score | lowest_score |
|---|---|---|
| 1 | 90 | 82 |
| 2 | 89 | NULL |
| 3 | 94 | NULL |
NULL이 GREATEST()랑 LEAST()에 미치는 영향
이제 진짜 재밌는 부분이야. 테이블 값들 중에 NULL도 있을 수 있잖아. 이미 알다시피 NULL은 데이터가 없거나 모르는 값을 뜻하는 신비한 존재야. 그럼 NULL이 PostgreSQL에서 GREATEST()랑 LEAST()에 들어가면 어떻게 되는지 보자.
NULL의 동작:
PostgreSQL에서 GREATEST()랑 LEAST() 함수는 좀 특별하게 동작해. 이 함수들은 NULL 값을 무시하고, 인자 중에서 제일 크거나 작은 값을 찾아줘. 중요: 단, 모든 인자가 NULL이면 결과도 NULL이야.
예시:
SELECT
GREATEST(10, 20, NULL, 5) AS greatest_value,
LEAST(10, 20, NULL, 5) AS least_value;
결과:
| greatest_value | least_value |
|---|---|
| 20 | 5 |
보다시피 NULL은 무시되고, 함수는 남아있는 값들(10, 20, 5) 중에서 최대/최소를 돌려줘.
이번엔 모든 인자가 NULL일 때 예시:
예시:
SELECT
GREATEST(NULL, NULL) AS greatest_nulls,
LEAST(NULL, NULL) AS least_nulls;
결과:
| greatest_nulls | least_nulls |
|---|---|
| NULL | NULL |
NULL 문제를 어떻게 피할까?
PostgreSQL은 기본적으로 NULL을 무시하지만, 가끔은 다른 동작이 필요할 수도 있어. 예를 들어, NULL을 0이나 다른 기본값으로 간주해서 최대/최소를 구하고 싶을 때가 있지. 이럴 땐 COALESCE() 함수를 쓰면 돼.
COALESCE(arg1, arg2, ...) 함수는 인자 중에서 첫 번째로 NULL이 아닌 값을 돌려줘. 이걸로 GREATEST()나 LEAST()에 넘기기 전에 NULL을 원하는 값으로 바꿀 수 있어.
예시 1: NULL을 0으로 바꾸기
예를 들어, 점수가 NULL이면 0점으로 간주하고 싶다고 해보자. COALESCE()로 기본값을 넣어줄 수 있어.
원본 테이블은 이래:
| student_id | exam_1 | exam_2 | exam_3 |
|---|---|---|---|
| 1 | 90 | 85 | 82 |
| 2 | NULL | 89 | NULL |
| 3 | NULL | NULL | 94 |
쿼리:
SELECT
student_id,
GREATEST(
COALESCE(exam_1, 0),
COALESCE(exam_2, 0),
COALESCE(exam_3, 0)
) AS highest_score,
LEAST(
COALESCE(exam_1, 0),
COALESCE(exam_2, 0),
COALESCE(exam_3, 0)
) AS lowest_score
FROM students_scores;
결과:
| student_id | highest_score | lowest_score |
|---|---|---|
| 1 | 90 | 82 |
| 2 | 89 | 0 |
| 3 | 94 | 0 |
예시 2: NULL을 다른 컬럼 값으로 바꾸기
가끔은 0 같은 고정값 대신, 다른 컬럼 값을 넣고 싶을 때도 있어. 예를 들어 exam_3이 없으면 exam_1 값을 대신 쓰고 싶을 때!
SELECT
student_id,
GREATEST(
exam_1,
exam_2,
COALESCE(exam_3, exam_1)
) AS highest_score
FROM students_scores;
테이블이 이렇게 있다고 해보자:
| student_id | exam_1 | exam_2 | exam_3 |
|---|---|---|---|
| 1 | 90 | 85 | 82 |
| 2 | NULL | 89 | NULL |
| 3 | 70 | NULL | NULL |
쿼리 결과:
| student_id | highest_score |
|---|---|
| 1 | 90 |
| 2 | 89 |
| 3 | 70 |
실전 케이스
케이스 1: 최대 할인 찾기
| order_id | discount_1 | discount_2 | discount_3 |
|---|---|---|---|
| 101 | 5 | 10 | 7 |
| 102 | NULL | 3 | 8 |
| 103 | 15 | NULL | NULL |
| 104 | NULL | NULL | NULL |
orders 테이블에서 각 주문마다 세 가지 할인 타입이 있을 수 있어. 각 주문별로 최대 할인을 찾아야 해.
SELECT
order_id,
GREATEST(discount_1, discount_2, discount_3) AS max_discount
FROM orders;
결과:
| order_id | max_discount |
|---|---|
| 101 | 10 |
| 102 | 8 |
| 103 | 15 |
| 104 | NULL |
케이스 2: 상품의 최소 가격 찾기
products 테이블에는 상품 가격이 USD, EUR, GBP 세 통화로 저장돼 있어. 각 상품별로 최소 가격을 찾아야 해.
| product_id | price_usd | price_eur | price_gbp |
|---|---|---|---|
| 1 | 100 | 95 | 80 |
| 2 | NULL | 150 | 140 |
| 3 | 200 | NULL | NULL |
| 4 | NULL | NULL | NULL |
SELECT
product_id,
LEAST(price_usd, price_eur, price_gbp) AS lowest_price
FROM products;
| product_id | lowest_price |
|---|---|
| 1 | 80 |
| 2 | 140 |
| 3 | 200 |
| 4 | NULL |
모든 가격이 NULL이면 결과도 NULL이야
GREATEST()랑 LEAST() 쓸 때 흔한 실수
실수 1: NULL 때문에 예상치 못한 결과.
강의 앞부분에서 NULL이 PostgreSQL에서 GREATEST()랑 LEAST()에 어떻게 영향을 주는지 자세히 봤지. 가장 흔한 실수는, 다른 DBMS에서 NULL이 하나라도 있으면 결과가 전부 NULL이 되는 걸 기대하는 거야. PostgreSQL은 다르거든.
실수 예시: 인자 중에 NULL이 있으면 함수가 항상 NULL을 돌려줄 거라고 착각할 수 있어. 그래서 쓸데없이 모든 인자에 COALESCE()를 써서 쿼리가 복잡해지고 느려질 수도 있어. 사실 NULL은 그냥 무시해도 되는 상황이 많아.
실수 2: GREATEST()랑 LEAST()를 타입이 안 맞는 값에 쓰기.
GREATEST()랑 LEAST() 함수는 같은 데이터 타입이거나 서로 자동 변환 가능한 타입끼리만 비교할 수 있어. 완전히 다른 타입을 비교하려고 하면 에러가 나.
실수 예시: 데이터 타입이 안 맞는다는 에러 메시지를 받게 될 거야.
GO TO FULL VERSION