전에 SAPDB 에서는 페이징을 위한 쿼리 때문에 한참을 고민했었던 적이 있습니다.
SAPDB 에서는 서브쿼리에서의 ORDER BY 지원, 인덱스 힌트 지원이 안되더라구요...
결국 온간 방법을 동원한 끝에 나온 결론이...
쿼리로 모든것을 해결하려 하지 말자...였습니다.
이번에 알려드릴 팁은 SAPDB의 서브쿼리와 JSP 에서의 페이지 처리를 이용하는 것입니다.
▶ 원리는 이렇습니다.
서브쿼리를 이용하여 서브쿼리내에서 ORDER BY 가 지원되지 않는다면 오름차순 정렬로 게시물이 추출 될 것 입니다.
만약 아래와 같은 데이터가 있다고 합시다.
번호 이름 작성일자
--------------------------
1 오이군 2002-01-01
2 가지군 2002-01-02
3 호박군 2002-01-03
4 신정호 2002-01-04
5 사오정 2002-01-05
6 손오공 2002-01-06
7 저팔계 2002-01-07
보통 게시판을 작성할때 게시물을 추가하면 위와 같은 형식으로 레코드가 추가 됩니다.
그런데 게시판이라 하면 아래와 같이 최근 글부터 내림차순으로 정렬이 되어 블럭단위로 보여주게 되어있습니다.
번호 이름 작성일자
--------------------------
7 저팔계 2002-01-07
6 손오공 2002-01-06 ◀ 1 Page
5 사오정 2002-01-05
--------------------------
4 신정호 2002-01-04
3 호박군 2002-01-03 ◀ 2 Page
2 가지군 2002-01-02
--------------------------
1 오이군 2002-01-01 ◀ 3 Page
하지만 SAPDB 에서는 서브쿼리내에서의 ORDER BY 를 허용하지 않기 때문에 일반적인 방법으로는 불가능 합니다.
그래서 제가 생각한 것이 처음부터 레코드를 가장 밑에서 부터 블럭단위로 읽은 후 다시 내림차순 정렬을 하는 것이었습니다.
그럼 한 페이지에 3개씩 게시물을 보여준다고 하면 아래와 같이 읽어지게 됩니다.
번호 이름 작성일자
--------------------------
1 오이군 2002-01-01 ◀ 3 Page
--------------------------
4 신정호 2002-01-04
3 호박군 2002-01-03 ◀ 2 Page
2 가지군 2002-01-02
--------------------------
7 저팔계 2002-01-07
6 손오공 2002-01-06 ◀ 1 Page
5 사오정 2002-01-05
즉, 레코드를 위에서 밑으로 순차적으로 읽는것이 아니라 위와 같이 밑에서 위로 거꾸로 읽는 것입니다.
오라클이나 MySQL 등에서 쓰이는 일반적인 방법으로는 먼저 내림차순 정렬후에 블럭을 나누는 것인데 여기서는 블럭을 먼저 나눈후 내림차순정렬을 하는 것입니다.
역순으로 레코드를 읽는것도 의외로 간단합니다.
어차피 페이징 리스트 및 전체 게시물 수를 보여주려면 전체 레코드 합계가 필요하므로 일단 전체 레코드 합계를 구합니다.
그리고 아래와 같이 계산을 하여 쿼리문을 작성합니다.
(※ 여기서 페이지 번호는 0 부터 시작합니다.)
값1 = [한 페이지에 보여줄 게시물 수]
값2 = ([전체 레코드 합계] - ([값1] - 1)) - ([페이지번호] * [값1])
SELECT rnum, field1, field2 FROM (
SELECT field1, field2, ROWNO AS rnum FROM table_name
) WHERE ROWNO <= [값1] AND rnum >= [값2] ORDER BY rnum DESC
위의 쿼리처럼 마지막에 ORDER BY rnum DESC 를 하면 나누어진 블럭내에서 내림차순 정렬을 하여 최근 레코드 부터 보여줍니다.
이해를 돕기 위하여 아래의 제가 테스트한 JSP 소스의 일부를 참고 하시기 바랍니다.
--------------------------------------- JSP 소스코드 ----------------------------------
int t_page = 0; // 현재 페이지번호
int t_page2 = 0; // 쿼리를 위한 페이지 계산 결과값
int total_data = 0; // 전체 데이터
String s_page = "0"; // 데이터 시작 rnum 값
String elimit = "4"; // 한 페이지에 출력될 총 게시물 수
String search_val = ""; // 검색어
String query = null; // 쿼리를 위한 String 변수
String tb = ""; // 테이블 출력을 위한 String 변수
ResultSet rs = null;
Statement stmt = null;
// 전체데이터 개수 얻기
query = "SELECT COUNT(*) AS total FROM guestbook";
try {
stmt = db_conn.createStatement();
rs = stmt.executeQuery(query);
rs.next();
total_data = rs.getInt("total");
}
catch (Exception e) { out.print(e.getMessage()); }
// 페이지 설정
Integer iii = null;
if (request.getParameter("page") != null) { t_page = Integer.parseInt(request.getParameter("page")); }
else { t_page = 0; }
t_page2 = (total_data - (Integer.parseInt(elimit) - 1)) - (t_page * Integer.parseInt(elimit));
if (t_page2 < 0) { t_page2 = 0; }
iii = new Integer(t_page2);
s_page = iii.toString();
// 쿼리
query = "SELECT rnum, NAME, REGDATE, EMAIL, COMMENT FROM";
query += "(SELECT NAME, REGDATE, EMAIL, COMMENT, ROWNO AS rnum FROM GUESTBOOK)";
query += "WHERE ROWNO <= " + elimit + " AND rnum >= " + s_page + " order by rnum desc";
--------------------------------------- JSP 소스코드 끝 -------------------------------
그리고 아래는 PHP로 작성된 예제의 일부 입니다.
--------------------------------------- PHP 소스코드 ----------------------------------
$elimit = 3; // 한 페이지에 표시할 게시물 수
// 전체데이터 개수 얻기
$query = "SELECT COUNT(*) AS total FROM guestbook";
$result = mysql_query($query, $db_conn);
$row = mysql_fetch_assoc($result);
$total_data = $row[total];
// 페이지 설정
if (!empty($HTTP_GET_VARS[page])) { $t_page = $HTTP_GET_VARS[page]; }
else { $t_page = 0; }
$t_page2 = ($total_data - ($elimit - 1)) - ($t_page * $elimit);
if ($t_page2 < 0) { $t_page2 = 0; }
// 쿼리
$query = "SELECT rnum, NAME, REGDATE, EMAIL, COMMENT FROM";
$query .= "(SELECT NAME, REGDATE, EMAIL, COMMENT, ROWNO AS rnum FROM GUESTBOOK)";
$query .= "WHERE ROWNO <= ".$elimit." AND rnum >= ".$t_page2." order by rnum desc";
--------------------------------------- PHP 소스코드 끝 -------------------------------
|