본문 바로가기
나도 공부한다/SQL

프로그래머스 SQL - EXTRACT, GROUP BY

by 꾸빵이 2024. 6. 11.

Oracle 기준으로 풀었습니다.

 

extract 함수

날짜 유형의 데이터에서 특정 정보만 추출할 수 있는 함수. 

 

예를 들어 DATE 형식인 컬럼 이름이 birth라고 하고 일자만 추출하고 싶다면 extract(day from birth) 라고 쓰면 된다.

이 때 컬럼 타입은 DATE, TIMESTAMP, INTERVAL이어야한다.

EXTRACT('추출하려는 날짜 요소' FROM 컬럼이름)

 

group by절

특정 칼럼을 기준으로 같은 값을 묶는 SQL 명령어이다.

기준 칼럼은 여러개를 지정할 수 있으며, 명시된 칼럼 순서대로 그룹화된다.

예를 들어 group by year, month 는 동일한 연도별로 그룹이 만들어지고, 연도별 그룹을 월별로 다시 그룹화한다.

avg, count, min, max, sum과 같은 집계함수로 그룹에 조건을 설정할 수 있다.

 

 


 

관련 프로그래머스 문제

 

3월에 태어난 여성 회원 목록 추출하기 Lv2

YYYY-MM-DD 형식으로 주어진 DATE에서 3월에 태어난 데이터만 추출해야한다.

extract 함수를 사용했는데, 시, 분, 초도 함께 출력되어 2024-06-11 00:00:00 형태로 출력된다.

그래서 TO_CHAR로 날짜 정보만 문자열 형태로 변환하여 시간 정보를 잘라냈다.

SELECT MEMBER_ID, MEMBER_NAME, GENDER, TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD') as DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE GENDER = 'W' AND TLNO IS NOT NULL AND EXTRACT(MONTH FROM DATE_OF_BIRTH) = '03'
ORDER BY MEMBER_ID

 

여기서 의문이 생겼다.

원본 테이블에서는 date_of_birth에 연,월,일 정보만 있었는데 왜 extract를 적용하니 시간까지 다 나오는걸까?

oracle에서 DATE 타입은 날짜와 시간 정보를 모두 포함하고 있어서 그렇다고 한다.

즉, 사용자가 데이터베이스에 시간 정보를 입력하지 않아도 자동으로 00:00:00으로 설정되는 것이다.

이는 select문으로 확인해볼 수 있었다. 

 

꼭 extract 함수로만 풀 수 있는 문제는 아니다. SUBSTR을 이용하여 월 정보만 잘라내서 비교해도 되고, TO_CHAR로 month만 문자열 변환하여 비교해도 된다.

 

잘 쓰이지 않는 함수의 경우 문법을 잊어버릴 수 있으니 다른 풀이법도 반드시 알아두자.

SELECT MEMBER_ID, MEMBER_NAME, GENDER, TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD') as DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE GENDER = 'W' AND TLNO IS NOT NULL AND SUBSTR(TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD'), 6, 2) = '03'
ORDER BY MEMBER_ID

 

SELECT MEMBER_ID, MEMBER_NAME, GENDER, TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD') as DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE GENDER = 'W' AND TLNO IS NOT NULL AND TO_CHAR(DATE_OF_BIRTH, 'MM') = 3
ORDER BY MEMBER_ID

 

 

재구매가 일어난 상품과 회원 리스트 구하기 Lv2

 

그룹화하고 having으로 그룹화된 데이터에 조건을 적용하는 문제이다.

SELECT USER_ID, PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(PRODUCT_ID) > 1
ORDER BY USER_ID, PRODUCT_ID DESC

 

product_id를 그룹으로 묶어야하는데 왜 group by에 group_id도 써야하지? 라고 생각할 수 있다.

 

'동일한 회원'이 '동일한 상품'을 여러번 구매한 경우를 찾는 것이므로, 그룹화 기준이 두 개인 것이다.

만약 product_id로만 그룹화한다면 해당 상품을 구매한 경우가 하나의 그룹으로 묶이게 된다.

 

참고로 group by 절을 사용할 때 반드시 select 문에 있는 모든 열을 넣어주거나 집계 함수로 만들어줘야한다. 따라서 gropu by에 product_id만 있는 경우엔 에러가 발생한다.