프로그래머스나 해커랭크에서 sql 문제를 풀다 보면 with 문을 쓰면 더 간결해 지겠구나. 라는 생각이 들 때가 있어요. 이 with절이 그냥 단순하게 실행 결과를 임시로 저장해 두고 쓴다. 정도로만 알고 있었어요. 그런데, recursive하게 써 먹을 수도 있었어요. 꽤 오랜 시간 헤멘 끝에 문서를 보고 약간이나마 이해를 할 수 있게 되었는데요. 이래서 영어 공부가 필요한가 봅니다. 예제 문제를 보면서 같이 쿼리를 작성해 봅시다.

 


 먼저, test 테이블에는 id와 par가 저장되어 있어요. par가 -1인 경우에는 부모가 없다는 뜻이고요. par가 -1이 아닌 0보다 큰 정수라면, 부모가 있다는 뜻입니다. 예를 들어, id가 6인 노드의 부모는 4임을 의미합니다. 이 데이터는 포레스트 형식을 만족해요. 우리는 3의 자식과 자식의 자식들, ... 을 모두 출력할 건데요. 문서에서 with recursive가 어떻게 동작하는지 설명이 상세하게 나와 있어요. 이를 참고해서 작성을 한 쿼리는 아래에 있습니다.

 

 

 뭔가 어려워 보이지만, (1)이라고 주석을 친 쿼리 문과 (2)라고 주석을 친 쿼리문을 보면서 천천히 이해해 봅시다. 먼저, 3의 자식들을 출력하기 위해서는, test라는 테이블에서 par가 3인 것들만 찾아주면 됩니다.

 

 

 그러면 요런 결과값이 나타납니다. 제가 링크한 문서에 따르면 이 set가 initial row set입니다. 여기까지 괜찮습니다. 다음에 (2) 라고 표시한 부분이 additional row set인데요. (2)에서 rec, e1이라고 표시한 것은 위 그림의 set를 의미해요. id가 5, 7, 11인 것들입니다.

 

 

 다음에 test, e2는 이것을 의미하는데요. 이 둘을 카티션 곱 하는데, e1.id와 e2.par가 같은 것만 뽑는답니다. 이 말은 e2.par가 5이거나 7이거나 11인 것만 뽑는다는 의미입니다.

 

 

 그러면 결과는 요래 나올 겁니다. 이것을 row set (1)이라고 합니다. 다음에 또 돌 건데, rec이 어느 것을 의미하나요? 위에 있는 그림의 결과 셋을 의미합니다. 다음에 e2는 test를 의미하는데요.

 

 

 그러면, 이 쿼리가 또 재귀적으로 수행되면 어떤 것이 뽑힐까요?

 

 

 1번째로 뽑힌 row set의 id가 8, 10, 13, 14였고, 이것이 e1이였습니다. e2.par는 test에서 뽑아올 겁니다. 그러면 test에서 par가 8이거나 10이거나 13이거나 14인 것만 뽑혀올 겁니다.

 

 

 이 결과 셋을 row set (2)라고 하겠습니다.

 

 


 그 다음에는 어떤 일이 일어날까요?

 

 

 rec가 row set (2)를 의미합니다. row set (2)의 id는 15만 있었습니다. rec과 test를 카티션 곱 할 텐데 이 중에 e1.id = e2.par이려면, e2.par가 15여야 합니다. 그런데, 그런 데이터는 없습니다.

 

  

 따라서 결과가 아무 것도 나오지 않게 되고, 이 때 재귀가 끝나게 됩니다.

 

 

 그래서 실행 결과는 위와 같습니다. 이제 문서에서 나온 with recursive 문을 간단하게 도식화 시켜 봅시다.

 


 대충 이런 것이였는데요. 먼저 (1)에 의해서, 1이 먼저 select가 될 거에요. 다음에 (2)가 실행될 텐데요. iter는 무엇을 의미하나요? 이전 결과값을 의미해요. 이전 결과값은 어떤 것인가요?

 

 

 이것입니다. 여기서 n < 2인 record에 대해서 n + 1을 출력하라고 했습니다. n < 2인가요? 그러므로, 그 다음 결과 셋은 아래 그림에서 노란색으로 칠한 부분입니다.

 

 

 그 다음에 (2)가 실행될 때 iter는 노란색 부분을 의미해요. iter에서 select n + 1을 할 건데요. 문제는 n < 2인 것이 없어요. 그러므로, 그 다음 결과셋이 없고 따라서 재귀가 끝나게 됩니다. 이 정도만 이해하시면 될 듯 하네요.