dalgorithm
달공의 개발기
dalgorithm
전체 방문자
오늘
어제
  • 분류 전체보기 (170)
    • Back-end (0)
    • Java (11)
    • 자료구조 (7)
    • Network (31)
    • Database (9)
    • Baekjoon Online (24)
    • 클라우드 (6)
    • Android (15)
      • Kotlin (14)
    • AI (27)
      • Machine Learning&Deep Learn.. (27)
    • Web (23)
      • Webhacking (17)
      • WebProgramming (6)
    • 기술면접 (1)
      • JAVA&자료구조 (0)
      • Spring (0)
      • 컴퓨터구조&운영체제 (0)
      • 네트워크 (0)
      • 데이터베이스 (0)
    • CTF 스터디 (15)
    • 대외활동 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • CTF
  • db
  • 데이터베이스
  • python #백준
  • cs
  • java
  • 네트워크
  • 포너블
  • Guacamole
  • 코드리뷰
  • 클라우드
  • 인공지능
  • 웹해킹
  • kotlin
  • 침입탐지
  • 딥러닝
  • 자료구조
  • 머신러닝
  • gcp
  • 자바

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
dalgorithm

달공의 개발기

[MySQL] WITH, WITH RECURSIVE 사용법
Database

[MySQL] WITH, WITH RECURSIVE 사용법

2022. 10. 10. 19:49
728x90

 


CTE (Common Table Expression) 이란?

 

CTE란 기존의 뷰나 파생 테이블, 임시 테이블 등으로 사용되는 것들을 대신할 수 있고, 보다 더 간결한 표현을 사용할 수 있따는 장점이 있다. CTE는 Non-Recursive(비재귀) CTE 와 Recursive(재귀) CTE 로 두가지 종류가 있다.

 

WITH 구문은 메모리 상에 가상의 테이블을 저장할 때 사용된다.

RECURSIVE의 여부에 따라 재귀, 비재귀 두 가지 방법으로 사용 가능하다.

 

WITH CTE_테이블명(열이름1, 열이름2, 열이름3...)
AS
(
	<쿼리문>
)
SELECT 열이름1, 열이름2, 열이름3 ... FROM CTE_테이블명
--------------------------------------------------------------
WITH [RECURSIVE] TABLE명 AS (
    SELECT - # 비반복문. 무조건 필수
    [UNION ALL] # RECURSIVE 사용 시 필수. 다음에 이어붙어야 할 때 사용
    SELECT - 
    [WHERE -] # RECURSIVE 사용 시 필수. 정지 조건 필요할 때 사용
)

 


❓프로그래머스 59413번

프로그래머스 SQL. 입양 시각 구하기2 

(https://school.programmers.co.kr/learn/courses/30/lessons/59413)

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

ANIMAL_OUTS 테이블로부터 

'보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.'

에 대한 결과를 출력해야한다.

 

|  시도

처음에는 ANIMAL_OUTS에 있는 DATETIME 값에 대해 깊게 생각해보지 않은 채로 바로 아래와 같이 시도하였다.

SELECT HOUR(DATETIME) AS HOUR, COUNT(DATETIME) AS COUNT
FROM ANIMAL_OUTS
WHERE  HOUR(DATETIME) >= 0 and HOUR(DATETIME) < 23
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME) ASC;

 

실행결과는 0부터 23시까지에 대한 결과가 아닌, ANIMAL_OUTS에 존재하는 시간 값에 대해서만 나와 9시에 대한 정보부터 나오는 문제가 있었다. 풀다가 도저히 감이 오지 않아 해결법을 찾아 보던 중 WITH RECURSIVE문을 사용하는 방법을 알게 되었다. 

 

위에서 언급한 Recursive CTE를 통해 WITH  RECURSIVE구문을 사용한다. WITH RECURSIVE를 통해 가상의 테이블을 생성하고 문제에서 주어지는 ANIMAL_OUTS와 JOIN 연산을 통해 해결하는 방법이다. 

 

우선 'SELECT ROW_NUMBER() OVER(ORDER BY DATETIME)-1 AS HOUR'을 통해 초기값으로 하는 가상의 테이블 Y를 생성한다. 

 

특정 테이블의 행번호를 붙여서 데이터를 조회를 해야할 때, ROW_NUMBER()을 사용하면 된다.

아래와 같은 경우, ANIMAL_OUTS 테이블에서  DATETIME을 기준으로 행번호를 붙여 정렬하는 쿼리다.

문제에서 0시부터 23시까지를 요구하고 있으므로, LIMIT 24와 HOUR에 대해 -1 처리를 해주었다.

 

WITH RECURSIVE Y AS (
SELECT ROW_NUMBER() OVER(ORDER BY DATETIME)-1 AS HOUR
FROM ANIMAL_OUTS 
LIMIT 24 )

 

그 다음으로는 가상의 테이블 Y와 ANIMAL_OUTS에 대해 LEFT JOIN을 해준다. JOIN문은 생각보다 간단하지만, 처음 접하는 WITH RECURSIVE 개념으로 해결하는데 많은 자료를 찾아보게 되었던 문제이다.

 

SELECT HOUR , COUNT(ANIMAL_ID) AS COUNT
FROM Y
LEFT JOIN ANIMAL_OUTS
ON DATE_FORMAT(DATETIME,"%H") = Y.HOUR
GROUP BY HOUR
ORDER BY HOUR

 

아래는 성공적으로 제출된 최종 답안이다.

 

✅ 최종 답안

WITH RECURSIVE Y AS (
SELECT ROW_NUMBER() OVER(ORDER BY DATETIME)-1 AS HOUR
FROM ANIMAL_OUTS 
LIMIT 24 )

SELECT HOUR , COUNT(ANIMAL_ID) AS COUNT
FROM Y
LEFT JOIN ANIMAL_OUTS
ON DATE_FORMAT(DATETIME,"%H") = Y.HOUR
GROUP BY HOUR
ORDER BY HOUR
728x90

'Database' 카테고리의 다른 글

[DB] Redis 레디스  (0) 2022.10.12
[DB] Transaction 트랜잭션  (0) 2022.10.10
[DB] 정규화 & 비정규화  (0) 2022.10.07
[DB] Index & B-Tree  (2) 2022.10.05
[DB] SQL vs NoSQL  (4) 2022.10.03
    'Database' 카테고리의 다른 글
    • [DB] Redis 레디스
    • [DB] Transaction 트랜잭션
    • [DB] 정규화 & 비정규화
    • [DB] Index & B-Tree
    dalgorithm
    dalgorithm

    티스토리툴바