일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 웹서비스 기획
- five lines challenge
- 강화학습
- CASE WHEN
- 재현율
- 평가 지표
- Batch Normalization
- recall
- 데이터 분석
- ifnull
- 데이터 전처리
- 데이터 프로젝트
- 오차 행렬
- 빠르게 실패하기
- 결정트리
- DecisionTree
- nvl2
- 감정은 습관이다
- 비지도학습
- Normalization
- 지도학습
- 백엔드
- layer normalization
- 정밀도
- NULLIF
- LAG
- sorted
- NVL
- beautifulsoup
- SQL
- Today
- Total
Day to_day
재귀 쿼리 WITH RECURSIVE 본문
프로그래머스 문제를 풀면서 오늘도 어려웠던 것 중에 재귀 쿼리? WITH RECIRSIVE라는 것을 처음 봤다!
이렇게 처음보는 문법 같은 경우엔 신기하기도 하고, 내가 배운 파이썬이랑은 또 어떤 점이 비슷한지 비교하면서 배우면 더욱 빨리 습득할 수 있는 것 같다.
그래서 오늘도 정리를 해보잣!
지시사항
보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.
정답 코드
WITH RECURSIVE NUMBER AS (
SELECT 0 AS N
UNION ALL
SELECT N+1
FROM NUMBER
WHERE N < 23
)
SELECT N, COUNT(ANIMAL_OUTS.DATETIME) AS COUNT
FROM NUMBER
LEFT JOIN ANIMAL_OUTS
ON HOUR(ANIMAL_OUTS.DATETIME) = NUMBER.N
GROUP BY N;
실행 결과
설명
재귀 쿼리
WITH RECURSIVE
RECURSIVE는 재귀라는 의미를 갖고 있고 의미대로 쿼리를 반복적으로 실행할 때 사용한다.
재귀 쿼리를 작성하는 법
보통 UNION 혹은 UNION ALL을 함께 사용해서 위와 같은 형식으로 사용한다.
Anchor member에서 시작할 지점을 select 한 후에 어떻게 반복할 것인가는 Recursive member에 넣는다.
Where절에는 부등호를 통한 끝 지점을 알려주는 Termination condition 구간을 만든다.
그리고 만든 쿼리를 사용하는 Query that uses CTE 파트를 만든다.
<활용 예시>
WTIH RECURSIVE NUMBER AS (
SELECT 0
UNION ALL
SELECT N+1
FROM NUMBER
WHERE N+1 <= 10
)
SELECT N
FROM NUMBER;
⇒ ‘N+1 <= 10’이라는 것은 SELECT N+1으로 사용되기 때문에 10 이하 숫자까지만 추출된다.
WTIH RECURSIVE NUMBER AS (
SELECT 0
UNION ALL
SELECT N+1
FROM NUMBER
WHERE N <= 10
)
⇒ 단 위와 같은 상황의 경우 SELECT N+1 이므로 N ≤ 10으로 했기 때문에 N이 11까지 숫자가 추출된다. 처음 예시와 같은 결과를 갖기 위해서는 N ≤ 11로 바꾸든지, N을 N+1로 바꿔야 한다.
다시 오늘의 문제로 돌아와서 살펴보자!
WITH RECURSIVE NUMBER AS (
SELECT 0 AS N
UNION ALL
SELECT N+1
FROM NUMBER
WHERE N < 23
)
SELECT N, COUNT(ANIMAL_OUTS.DATETIME) AS COUNT
FROM NUMBER
LEFT JOIN ANIMAL_OUTS
ON HOUR(ANIMAL_OUTS.DATETIME) = NUMBER.N
GROUP BY N;
재귀 쿼리로 NUMBER라는 쿼리를 만들었고 NUMBER를 기준으로 ANIMAL_OUTS를 조인했음을 알 수 있다.
SELECT N은 두 개의 테이블이 조인 후 실행되는 것이기 때문에 사용할 수 있다.
GROUP BY N으로 묶어주는 이유는 뭘까?
=> N으로 묶어야 값이 없더라도 0이 들어갈 수 있다.
이게 무슨 말이냐 하면...
SELECT N, COUNT(ANIMAL_OUTS.DATETIME) AS COUNT
FROM ANIMAL_OUTS
RIGHT JOIN NUMBER
ON HOUR(ANIMAL_OUTS.DATETIME) = NUMBER.N
GROUP BY HOUR(ANIMAL_OUTS.DATETIME);
예를 들어 다음과 같이 GROUP BY를 HOUR(ANIMAL_OUTS.DATETIME)을 기준으로 바꾸어봤을 때
아래와 같은 결과를 볼 수 있다.
여기서 값이 없는 DATETIME에 대해서는 추출되지 않는 것을 볼 수 있다.
하지면 지시 사항에서
" 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회"라는 말이 들어갔기 때문에 값이 없는 DATETIME의 경우에도 0으로 값이 들어가야 한다는 의미이다.
그래서 최종 코드를 살펴보자.
N으로 grouping을 하고 ANIMAL_OUTS.DATETIME에 대한 데이터만 COUNT 하는 값을 추출하는 코드이다.
WITH RECURSIVE NUMBER AS (
SELECT 0 AS N
UNION ALL
SELECT N+1
FROM NUMBER
WHERE N < 23
)
SELECT N, COUNT(ANIMAL_OUTS.DATETIME) AS COUNT
FROM NUMBER
LEFT JOIN ANIMAL_OUTS
ON HOUR(ANIMAL_OUTS.DATETIME) = NUMBER.N
GROUP BY N;
REF
SQL 문법 | 데이터 조회 및 필터 | 재귀 쿼리 RECURSIVE QUERY
'SQL' 카테고리의 다른 글
[MySQL] NOT IN을 사용할 때 주의할 점 (+ EXISTS와 비교하기) (0) | 2023.01.04 |
---|---|
[MySQL] 날짜 연산 DATE_ADD, DATE_SUB, DATEDIFF (+ LEAD, LAG) (0) | 2023.01.03 |
WITH 절 사용하기 (feat. PARTITION BY) (0) | 2022.11.04 |
CASE WHEN 사용하기 (0) | 2022.11.02 |
Null 치환하기 (0) | 2022.09.27 |