🔥 Vamos/DataBase
MARIA DB 에서의 재귀함수, WITH RECURSIVE
unikue
2024. 1. 8. 22:56
행을 여러개 생성해야 할 때, 오라클은 CONNECT BY 라는 깔끔한 문장이 있다.
이렇게 말이지.
SELECT
A.*
FROM
(
SELECT
LEVEL
FROM
DUAL
CONNECT BY LEVEL <= 24 -- LEVEL 24까지 생성
) A
;
하지만 MARIA DB, MYSQL에서는 재귀함수를 통해서 아래 행들을 부르고 부르고 또 불러야 한다. 언제까지? 내가 설정한 개수까지. WITH RECURSIVE로 시작하는 이 문장은, 처음에는 너무 어색했는데 자꾸 보다 보니까 조금 감이 생겼다.
WITH RECURSIVE A AS(
SELECT 1 AS LEVEL -- 기본 레벨로 삼는다
UNION ALL -- UNION ALL로 아래 생기는 것들을 모두 붙일것임
SELECT 1 + LEVEL -- 기본 1 + 레벨을 붙이므로 여기는 2부터 시작한다
FROM A
WHERE LEVEL < 10 -- 레벨이 9가 될때까지 이므로 총 1~10레벨이 생긴다.
) -- WITH RECURSIVE안에서 A라는것을 정의하는 것과 같음
SELECT
*
FROM A;
-- 이렇게 하면 위에 있는 오라클 구문과 레벨만 다른 동일 결과가 나오므로, 다른 식으로 더 확장시켜 보겠음.
WITH RECURSIVE A AS(
SELECT 1 AS LEVEL
UNION ALL
SELECT 1 + LEVEL
FROM A
WHERE LEVEL < 10
)
SELECT
R.FIRST
, R.SECOND
, R.RESULT
, FLOOR(R.RESULT * 0.5) DIVIDED -- RESULT로 간단하게 가져다 쓰려고 INNER TABLE을 하나 더 올렸다
FROM
(
SELECT
T.N1 FIRST
, T.N2 SECOND
, T.N1 + T.N2 RESULT -- 여기서는 바로 RESULT값을 쓰지 못하고 (T.N1+T.N2)*0.5로 해줘야 함. SELECT문은 가로로 붙기 때문
FROM
(
SELECT
ROUND((RAND() *2 +1) * 100000) N1
, ROUND((RAND() *3 +1) * 1000000) N2
FROM
A -- WITH RECURSIVE로 만든 행에다가 SELECT 를 붙여서 출력한다.
) T
) R
;
번외로, ROW_NUMBER()를 가지고 다른 테이블에서 행 개수만 따오는 방법도 있다.
이 방법은 ORACLE, MARIADB계열 양쪽 모두에 가능하다.
SELECT
ADDDATE('2023-01-25', INTERVAL (T.seq - 1) MONTH) AS SALARY_DATE
, M.ID
FROM
(
SELECT
R.*
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY TEAM_ID) AS seq
FROM TEAM
LIMIT 24 -- TEAM 테이블에서 ROW NUMBER만 24까지 가져온다 (동시에 TEAM_ID로 정렬도 함)
) R
) T
INNER JOIN MEMBER M ON 1=1 -- MEMBER 테이블과 카티션 조인을 함. 24개 * 멤버테이블 행개수만큼 곱한 결과가 나온다
ORDER BY M.ID, SALARY_DATE
;
* 이때 ROW_NUMBER는 행 개수 (정확히는 각 행의 순번)만 가져다 쓰는거고, TEAM 테이블 데이터를 가져오는게 아니다.