페이징 쿼리 질문드립니다~! 0 8 638

by 천만달러 [Tibero] [2021.11.02 10:13:20]


페이징 질문1.png (16,011Bytes)
페이징 질문2.png (82,595Bytes)
페이징 질문3.png (69,312Bytes)

안녕하세요. 저번에 구루비 고수님께서 만들어주셨던 쿼리에서 페이징을 넣으려고 하는데요

 

SELECT A.RNUM
    , A.CONTENTS_ID
    , A.TITLE
    , A.LANG_CD
    , A.UPDATE_DATE
    , A.COMP_TEXT
    , A.COMP_TYPE
FROM (
    SELECT CEIL ((ROW_NUMBER() OVER(ORDER BY B.UPDATE_DATE ASC)+0.00) / (10+0.00)) AS RNUM
        , B.CONTENTS_ID
        , B.TITLE
        , B.DESCRIPTION
        , B.LANG_CD
        , B.UPDATE_DATE
        , C.COMP_TEXT
        , C.COMP_TYPE
        , ROW_NUMBER() OVER(PARTITION BY B.CONTENTS_ID ORDER BY C.SORT_NO ASC) AS SORT_NO
    FROM TB_CONTENTS B, TB_CONT_COMPONENT C
    WHERE 1=1
    AND B.CONTENTS_ID = C.CONTENTS_ID(+)
    AND B.CONTENTS_TYPE = 'FOT'
    AND B.USE_YN = 'Y'
    AND B.DEL_YN = 'N'
    AND B.POC_CD = 'NO'
    AND B.LANG_CD = 'KO'
    AND C.COMP_TYPE(+) = 'A3'
    AND C.LANG_CD(+) = 'KO'
) A
WHERE 1=1
AND SORT_NO = 1
AND RNUM = 3
;

위 쿼리를 돌리면 아래 첫번째 사진처럼 RNUM이 3일때 정렬이 이상해지더라구요...

이유를 알수는 없었지만 

AND B.LANG_CD = 'KO'
AND C.COMP_TYPE(+) = 'A3'
AND C.LANG_CD(+) = 'KO'

위 쿼리 밑에 다시한번

ORDER BY C.SORT_NO ASC

이렇게 주면 그때는 정상으로 나와서 이렇게 사용하다가

제가 역순으로 정렬을 해야 해서 오더바이를 DESC로 하니까

이상하게 정렬이 안되는겁니다...

ASC일때는 RNUM이 1일때 10개씩 보여줬거든요

SELECT CEIL ((ROW_NUMBER() OVER(ORDER BY B.UPDATE_DATE ASC)+0.00) / (10+0.00)) AS RNUM

여기서 10+0.00이 부분이 10개를 보여준다 이런 말인데

ASC일때는 아래 두번째 사진처럼 잘 보여주는데

DESC를 넣으면 첫페이지가 7개 두번째 페이지가 10개...마지막 페이지에 남은  리스트를 보여주는데요...

 

SELECT CEIL ((ROW_NUMBER() OVER(ORDER BY B.UPDATE_DATE DESC)+0.00) / (10+0.00)) AS RNUM

ORDER BY C.SORT_NO DESC

 

위처럼 저렇게 DESC로 변경하면 3번째 사진처럼 첫 페이지가 7개가 나오고 정렬이 안되는데 도저히...모르겠습니다...

그리고 SORT_NO = 1 이것도 마지막에 조건을 줘야 쿼리가 돌아가더라구요...저 서브쿼리안에 넣으면 오류가 납니다...하...

고수님들 도와주세요...

by isNull [2021.11.02 10:25:26]

보니까 페이징은 전체 건수에 대해서 계산해서 하는데 sort_no가 1인거만 가져오려고 하니까 건수 차이가 나서 그런거 같네요.

페이징이 기존것도 맞지 않아 보입니다.

where 절에 sort_no 가 일단 건수를 변경시키고 잇는것으로 보이니

안쪽 쿼리의 전체 건수와 바깥 쿼리의 건수를 확인해보세요.

페이징 처리는 됐지만 sort_no가 1이 아닌건이 안나오는 것으로 보입니다.


by 천만달러 [2021.11.02 11:34:59]

내부 sort_no을 기준으로 가져와야 하는 값이 있어서 id로 바꾸면 안되는거 같아요

바꾼다고 해도 desc할때 첫 페이지에 10개가 안나오고 7개만 나오는건 그대로 입니다...

정렬이 잘안되요...저는 DESC로 정렬해도 ASC처럼 정렬이 됐으면 하는 방법이 궁금합니다 ㅠ

CEIL 이부분에 정렬을 CEIL ((ROW_NUMBER() OVER(ORDER BY B.CONTENTS_ID DESC)+0.00) / (10+0.00)) AS RNUM

이런식으로 바꾸면 마지막 페이지 정렬이 이상합니다 최근거 하나랑 나머지 마지막 리스트 이렇게 이상하게 나와요...

하....왜 그럴까요...


by 모래가흙흙 [2021.11.02 13:15:24]

어짜피 TB_CONTENTS B 의 update_time기준으로 잡을거면,  먼저 페이징 후  TB_CONT_COMPONENT와의 조인이 낫지 않을까 싶습니다


by isNull [2021.11.02 13:17:29]

저게 게시판이고 본문 댓글을 같이 표시하는 형식이면 조인해서 페이징해야 되는거라...

저게 맞을 수도 있어요. 단지... 맨 아래 WHERE SORT_NO = 1 이거 때문에 건수가 안맞는것으로 보입니다.


by 마농 [2021.11.02 13:33:14]

1. 제가 기존 질문에 알려드린거랑 쿼리가 다른데요?
2. SORT_NO 조건과 RNUM 조건을 동시에 주면 안되고 순차적으로 줘야 합니다.
3. 정렬은 유니크해야 합니다. update_date 만으로는 중복 가능하니 contents_id 를 추가하세요.
4. 정렬 기준이 ASC 맞나요? DESC 해야 하는게 아닌지?


by 천만달러 [2021.11.02 14:20:17]

CEIL ((ROW_NUMBER() OVER(ORDER BY B.CONTENTS_ID DESC)+0.00) / (10+0.00)) AS RNUM

여기 UPDATE_DATE에서 CONTENTS_ID이걸로 바꿨습니다. 

ROW_NUMBER() OVER(PARTITION BY B.CONTENTS_ID ORDER BY C.SORT_NO ASC) AS SORT_NO

여기서 C.SORT_NO ASC 이거는 SORT_NO에서 낮은거 하나를 가져오고 싶어서 이렇게 했는데 맞는건지 모르겠네요...

AND SORT_NO = 1
AND RNUM = 1

이렇게 주면 안된다고 하셔서 서브쿼리에 둘다 하나씩 넣어봤는데

둘다 안되더라구요...그래서 마지막에 줄수밖에 없는데 서브쿼리로 또 감싸야...하나요...................

너무 복잡해서 머리가 터질 거 같습니다 ㅋ;;


by 마농 [2021.11.02 14:28:14]

1. 네. 서브쿼리로 또 감싸야 합니다.
2. +0.00 은 불필요해 보이네요.

SELECT *
  FROM (SELECT CEIL(ROW_NUMBER() OVER(ORDER BY a.contents_id DESC) / 10) rnum
             , a.contents_id
             , a.title
             , a.lang_cd
             , a.update_date
             , a.comp_text
             , a.comp_type
          FROM (SELECT b.contents_id
                     , b.title
                     , b.description
                     , b.lang_cd
                     , b.update_date
                     , c.comp_text
                     , c.comp_type
                     , ROW_NUMBER() OVER(PARTITION BY b.contents_id ORDER BY c.sort_no) sort_no
                  FROM tb_contents b
                     , tb_cont_component c
                 WHERE 1=1
                   AND b.contents_id   = c.contents_id(+)
                   AND b.contents_type = 'FOT'
                   AND b.use_yn        = 'Y'
                   AND b.del_yn        = 'N'
                   AND b.poc_cd        = 'NO'
                   AND b.lang_cd       = 'KO'
                   AND c.comp_type(+)  = 'A3'
                   AND c.lang_cd  (+)  = 'KO'
                 ORDER BY b.update_date, b.contents_id
                ) a
         WHERE sort_no = 1
        ) a
 WHERE rnum = 3
;

 


by 마농 [2021.11.02 17:39:33]

페이징 쿼리의 장점을 살리지 못하는 쿼리입니다.
CEIL 로 인해 ROW_NUMBER 의 STOP 기능을 효율적으로 이용 할 수 없고
sort_no 로직은 전체범위 처리를 하게 됩니다.
우선 메인 테이블만으로 페이징 처리를 최적화 하고
comp_text 는 10건에 대해서만 조인하여 가져오는 방식이 좋습니다.
comp_type 은 어차피 조건 주고 가져오는 부분이라 굳이 select list 에 넣을 필요 없어 보이네요.
 

SELECT CEIL(rn / 10) rnum
     , contents_id
     , title
     , description
     , lang_cd
     , update_date
     , (SELECT MIN(comp_text) KEEP(DENSE_RANK FIRST ORDER BY sort_no)
          FROM tb_cont_component c
         WHERE c.contents_id = b.contents_id
           AND c.comp_type   = 'A3'
           AND c.lang_cd     = 'KO'
        ) comp_text
  FROM (SELECT ROW_NUMBER() OVER(ORDER BY contents_id DESC) rn
             , contents_id
             , title
             , description
             , lang_cd
             , update_date
          FROM tb_contents
         WHERE 1=1
           AND contents_type = 'FOT'
           AND use_yn        = 'Y'
           AND del_yn        = 'N'
           AND poc_cd        = 'NO'
           AND lang_cd       = 'KO'
        ) b
 WHERE rn >= 10 * (3 - 1) + 1
   AND rn <= 10 * 3
;

 

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