mysql 게시글 리스트, 댓글 개수, 첨부파일 조회 질문입니다. 0 4 4,110

by 신짱 [MySQL] [2019.01.28 00:08:27]


안녕하세요.

게시글 리스트 조회 시 댓글 개수를 가져오는것 까지는 해결했는데 여기에 첨부파일이 있으면 그 중 가장 먼저 업로드 된 파일도 하나 같이 조회를 할려고 합니다.

테이블은 다음과 같이 설계가 되어 있습니다.

<게시판 테이블>

게시글번호 제목 내용 글쓴이 작성일
1 블로그1 내용입니다1 관리자 2019-01-01
2 블로그2 내용입니다2 관리자 2019-01-02
3 블로그3 내용입니다3 관리자 2019-01-03
4 블로그4 내용입니다4 관리자 2019-01-04

<댓글 테이블>

댓글번호 게시글번호 내용 작성자
1 2 짱구댓글입니다 짱구
2 2 철수댓글입니다 철수
3 3 훈이댓글입니다 훈이
4 4 흰둥이댓글입니다 흰둥이

<첨부파일 테이블>

파일번호 게시글번호 파일이름 파일경로 파일사이즈
1 2 /file.jpg /2019/01/02 100
2 2 /file2.png /2019/01/02 200
3 3 /doc.txt /2019/01/03 150

위와 같이 데이터가 들어가 있다고 하면 아래와 같이 출력이 되길 원합니다.

<출력결과>

게시글번호 제목 글쓴이 작성일 댓글개수 파일이름 파일경로
1 블로그1 관리자 2019-01-01 0 null null
2 블로그2 관리자 2019-01-02 2 /file.jpg /2019/01/02
3 블로그3 관리자 2019-01-03 1 /doc.txt /2019/01/03
4 블로그4 관리자 2019-01-04 1 null null

게시글 리스트와 댓글개수는

select a.게시글번호, a.제목, a.글쓴이, a.작성일, count(b.댓글번호)

from 게시판 a left join 댓글 b on a.게시글번호 = b.게시글번호

group by a.게시글번호

로 구했는데 첨부파일까지 조회할려고 하니 잘 안되네요..

첨부파일이 여러개가 있다면 그 중 파일번호가 가장 작은걸 하나 불러올려고 합니다(제일 먼저 업로드된 순)

감사합니다.

by 마농 [2019.01.28 09:13:44]

1:m:n 조인을 한번에 하면 건수가 m*n 만큼 뻥튀기 됩니다.
1:m 조인 후 그룹바이 한뒤 다시 1:n 조인을 단계별로 하는 방법이 있습니다.
다만 이렇게 조인하는 방식은 페이징 처리를 염두에 두지 않은 방식인 듯 합니다.
1. 페이징 처리 전에 모든 정보를 다 가져오는 것은 비효율입니다.
  - 게시글만 페이징 처리 후에 한 페이지에 대해서만 조인을 하는 것이 좋습니다.
2. 그룹바이 구문도 지금 mySQL 에서만 허용되는 비표준 구문입니다.
  - mySQL 의 이 비표준 Group By 에 익숙해 있다가, 다른 DB 사용하시게 되면 적응 못할 수 있습니다.
  - 표준 구문 사용 권장합니다.
3. 추가 사항
  - 조인 대신 스칼라 서브쿼리를 이용할 수도 있습니다.
  - 댓글과 첨부 테이블에는 반드시 "게시글번호" 인덱스가 있어야 합니다.

-- 1. Group By 표준 구문 권장, 페이징 후 조인
SELECT a.게시글번호
     , a.제목
     , a.글쓴이
     , a.작성일
     , a.댓글개수
     , c.파일이름
     , c.파일경로
  FROM (SELECT a.게시글번호
             , a.제목
             , a.글쓴이
             , a.작성일
             , COUNT(b.댓글번호) 댓글개수
          FROM (-- 우선 페이징 처리 --
                SELECT 게시글번호, 제목, 글쓴이, 작성일
                  FROM 게시판
                 ORDER BY 게시글번호 DESC
                 LIMIT 0, 10
                ) a
          LEFT JOIN 댓글 b
            ON a.게시글번호 = b.게시글번호
         GROUP BY a.게시글번호             -- 여기까지만 사용하면 비표준
             , a.제목, a.글쓴이, a.작성일  -- 여기서부터 추가해야 표준
        ) a
  LEFT JOIN 첨부파일 c
    ON a.게시글번호 = c.게시글번호
   AND NOT EXISTS (-- Exists 구문을 활용하여 1건만 가져오기
                   SELECT 1
                     FROM 첨부파일 d
                    WHERE d.게시글번호 = c.게시글번호
                      AND d.파일번호   < c.파일번호
                   )
 ORDER BY 게시글번호 DESC 
;

-- 2. 스칼라 서브쿼리 사용 예
SELECT a.게시글번호
     , a.제목
     , a.글쓴이
     , a.작성일
     , (SELECT COUNT(b.댓글번호) FROM 댓글 b WHERE b.게시글번호 = a.게시글번호) 댓글개수
     , c.파일이름
     , c.파일경로
  FROM (-- 1. 우선 페이징 처리 --
        SELECT 게시글번호, 제목, 글쓴이, 작성일
          FROM 게시판
         ORDER BY 게시글번호 DESC
         LIMIT 0, 10
        ) a
  LEFT JOIN 첨부파일 c
    ON a.게시글번호 = c.게시글번호
   AND NOT EXISTS (-- 3. Exists 구문을 활용하여 1건만 가져오기
                   SELECT 1
                     FROM 첨부파일 d
                    WHERE d.게시글번호 = c.게시글번호
                      AND d.파일번호   < c.파일번호
                   )
 ORDER BY 게시글번호 DESC
;

 


by 신짱 [2019.01.28 11:50:42]

답변 감사드립니다!
말씀해주신 쿼리로 테스트 중인데 게시글번호로 정렬이 되지 않는 문제가 있습니다.

order by 게시글번호 desc 구문으로 정렬이 될거라 생각했는데

최종 출력결과가 게시글번호로 정렬이 되지 않고 뒤죽박죽으로 나오는데 이유를 알 수 있을까요..?

추가로 확인해보니 스칼라 서브쿼리를 이용한 방식은 제대로 정렬이 되는거 같은데

1번 방식으로 했을 때는 제대로 정렬이 안되는거 같습니다.


by 마농 [2019.01.28 12:15:47]

1차 정렬은 페이징 처리를 위한 정렬입니다.
정렬이 틀어지는 이유는 그룹바이나 조인 때문에 그렇습니다.
최종 결과에 대한 정렬을 위해 마지막으로 ORDER BY 구문 한번 더 써주셔야 합니다.


by 신짱 [2019.01.28 12:41:38]

답변 감사합니다ㅎㅎ

많은 도움되었습니다!!

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입