본문 바로가기

디버깅/MySQL, MariaDB

[SQL] 서브쿼리 (Sub Query)를 이용한 게시글의 댓글 갯수 출력

반응형



인턴 일을 그만두고 하루 이틀 사이에 혼자 한달동안 끙끙거리던 분량을 넘어선 코딩을 달렸었다. -_-

그리고 근근히 세세한 추가사항과 변경만 추가하고 1달을 코딩을 하지 않고 놀았다 (겁내 반성해야 겠다)

기존에 공부용으로 만들던 프로젝트를 다시 열어 몇가지 소소한 기능들을 추가 했는데. 막상 보니 글 제목에서 댓글 갯수 표시 하지 않아서 예전에 학원 다닐때 얼핏들었던 서브쿼리를 적용해보게 되었다. 



서브쿼리 단어는 거창한데 그냥 하나의 쿼리안에 다른 쿼리를 하나 더 이용하는 간단한 개념이다 (물론 말은 쉽지)

일종의 JOIN과 비슷한 쿼리인데 그 용도가 조금 다르다.

join의 경우 SELECT 문 자체를 합칠때 사용하는데 서브쿼리는 말 그대로 내가 원하는 쿼리를 조건에 맞게 합쳐줄수가 있기 때문.

그렇기 때문에 데이터가 많아진다면 서브쿼리가 Join보다 퍼포먼스에 더 큰 영향을 끼칠 것으로 추측된다.


그러므로 게시글과 댓글이 계속해서 증가한다면 댓글 갯수 컬럼을 하나 추가해서 따로 처리하는게 퍼포먼스적으로 더 나을수도 있다. 


여하튼 현재는 게시글 테이블(article)과 댓글 테이블(comment)이 나뉘어져 있고 어느 테이블에도 댓글 갯수가 따로 컬럼화 되어있지 않다고 가정한다. (댓글 갯수 컬럼이 있다면 그냥 join만 하면 간단하게 처리가 되겠지)


서브쿼리는 SELECT, FROM, WHERE 절에도 쓸수 있고 단일행 , 다중행 , 다중컬럼에도 쓸수 있다.

여기서 사용해볼 것은 SELECT에 단일 행으로 쓸것 같다 (??)



그럼 테이블 구조를 한번 보자


게시글(article) 테이블의 select 모습


댓글(comment) 테이블의 select 모습


개발도 그렇지만 쿼리도 복잡할수록 주제를 잘게 잘라서 생각해보면 된다. 우선 게시글을 리스트 형태로 출력하는 쿼리는 너무나 쉬울 것이다. 그리고 우리가 필요한건 댓글의 갯수이다. 근데 따로 갯수를 데이터화 하지 않았다.

고로 게시글의 댓글 갯수를 구하는 쿼리를 먼저 짠다음 합치면 될 것이다.  두 쿼리를 짜고 서브쿼리를 이용해서 합쳐주면 된다. 어떻게? 게시글과 일치하는 댓글 갯수로


의식의 흐름상 이런 흐름이 나왔다면 성공이다. 그럼 그럼 서브쿼리를 작성하기 전에 comment 테이블에서 댓글의 갯수를 구하는 쿼리부터 작성해보자


구조는 사실 뻔하고 비슷한데. parent_idx 컬럼이 있는 테이블이 댓글을 담당하는 comment 테이블이다 (이걸 모르신다면............... 크흠........)

우선 서브쿼리를 처음 부터 짜기 익숙치 않다면 두개의 쿼리를 따로 짜고 합치는게 쉬울 것이다.


원론적으로 우리는 게시글을 SELECT하는 쿼리를 먼저 짜게 되는데

SELECT title, content, .... FROM article_TB;

와 같은 형태가 될것이다.


다음으로 필요한건 댓글의 갯수를 SELECT 해오는 쿼리일 것이고. 대략 이런 형태를 가질 것이다.

SELECT count(*) FROM comment_TB comment WHERE comment.parent_idx = article.idx ) AS comment_cnt


이 쿼리가 문맥상으론 맞지 않을텐데 그 이유는 아직 쿼리를 붙이기 전이라서 article.idx라는 컬럼이 문맥상 존재하지 않기 때문이다.

만약 게시글의 idx가 10이라면 article.idx = 10 일테고, 그렇다면 10번 게시글에 달린 댓글의 갯수를 가져오게 된다. (테스트를 할때는 article.idx 자리에 구하고자 하는 게시글이 idx를 넣어보고 돌리면 된다)


자 이제 두개의 쿼리를 하나로 합쳐서 서브쿼리로 만들면 된다. (여기서 부터가 서브쿼리의 개념)


SELECT article.title, article.content,

(SELECT count(*) FROM comment_TB comment WHERE comment.parent_idx = article.idx ) AS comment_cnt)

FROM article_TB article;


가독성을 위해 한줄 띄었는데 이런식이 될 것이다. 약간의 부연 설명은 일단 두개의 FROM에서 테이블에 변수명을 지정해주었고

서브쿼리에서 WHERE절을 이용해 게시글의 idx과 댓글의 부모 인덱스.. 즉 댓글이 달린 게시글의 idx가 일치하는 댓글의 갯수를 SELECT 쿼리로 만들었고 그 값을 메인쿼리의 SELECT 절에 넣어주었다. 서브 쿼리는 댓글의 갯수가 될것이므로 AS를 이용해 comment_cnt로 이름을 지어주었다.


자바, 스프링에서 편리하게 view에 출력하려면 멤버 변수에 comment_cnt 변수를 추가하고 getter, setter를 추가한 뒤에

comment_cnt 변수를 출력해주면 끝!


group by를 이용하면 join을 이용해서도 구현이 가능하다


참조 :

http://ttend.tistory.com/619

http://www.sqlprogram.com/Basics/sql-subquery.aspx

반응형