계층형 게시판을 위한 두번째 알고리즘에 대해서 알아봅니다.
첫번째 계층형 게시판에서는 같은 레벨에 답글을 다는 경우, 가장 최근 답글이 동일한 레벨에서 가장 위에 표시되었습니다.
이번에는 가장 최근 답글이 동일한 레벨에서 마지막에 표시되도록 합니다.
설명을 위해 테이블에는 다음과 같은 컬럼들만 있다고 가정합니다. 실제로는 더 많겠죠.
No : 글번호(Primary Key)
Title : 글제목
Grp : 같은 주제를 갖는 게시물의 고유번호. 부모글과 부모글로부터 파생된 모든 자식글은 같은 번호를 갖습니다.
Depth : 같은 그룹내 게시물의 순서
게시판에 첫번째 글이 올라오면, 테이블에는 다음과 같은 정보가 저장됩니다.
=================================
No, Title , Grp, Depth
=================================
1, '안녕하세요' , 1, 'A'
=================================
새 글에서 No는 시퀀스로부터 받아온 값, Grp는 No와 동일한 값, Depth는 'A'입니다.
두번째 글과 세번째 글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
=================================
첫번째 글에 답글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
4, ' 반가워요 ', 1, 'AA'
=================================
답글의 경우, Grp는 부모글의 Grp 값, Depth는 부모글의 Depth에 'A'를 추가합니다.
첫번째 글의 답글에 답글이 올라옵니다. 즉, 네번째 글의 답글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
4, ' 반가워요 ', 1, 'AA'
5, ' 감사합니다 ', 1, 'AAA'
=================================
첫번째 글의 두번째 답글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
4, ' 반가워요 ', 1, 'AA'
5, ' 감사합니다 ', 1, 'AAA'
6, ' 환영합니다 ', 1, 'AB'
=================================
여기서, 두번째 답글이 첫번째 답글의 아래에 표시되려면, 동일한 그룹 번호에 있으면서, 부모의 Depth 문자열로 시작되고,
문자열의 길이가 부모의 Depth 문자열보다 하나가 큰 문자열 중 최대값을 찾아 Depth로 사용합니다.
여섯번째 게시물에 답글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
4, ' 반가워요 ', 1, 'AA'
5, ' 감사합니다 ', 1, 'AAA'
6, ' 환영합니다 ', 1, 'AB'
7, ' 감사합니다 ', 1, 'ABA'
=================================
네번째 게시물에 두번째 답글이 올라옵니다.
=================================
No, Title , Grp, Depth
=================================
3, '모임이 있습니다', 3, 'A'
2, '날씨가 맑습니다', 2, 'A'
1, '안녕하세요 ', 1, 'A'
4, ' 반가워요 ', 1, 'AA'
5, ' 감사합니다 ', 1, 'AAA'
8, ' 저도 방가 ', 1, 'AAB'
6, ' 환영합니다 ', 1, 'AB'
7, ' 감사합니다 ', 1, 'ABA'
=================================
검색 할 때는 Grp를 내림차순으로 Depth를 오름차 순으로 정렬하면 됩니다.
인덱스는 기본키와 Grp+Depth의 복합 인덱스를 설정하면 됩니다.
실제 오라클에서 테이블을 구성하고 검색해봅니다.
drop table qnaboard;
create table qnaboard
(no number,
title varchar2(100),
contents varchar2(4000),
writer varchar2(20),
wdate date,
grp number,
depth varchar2(1000));
drop sequence qnaboard_no_seq;
create sequence qnaboard_no_seq
start with 1
increment by 1;
create index qnaboard_no_idx on qnaboard(no) reverse;
alter table qnaboard
add constraint qnaboard_no_pk primary key (no);
문자열 처리를 위한 도우미 함수입니다. 문자열을 입력하면 마지막 문자를 다음 문자로 교체합니다.
예를 들어, 'AAABB'를 입력하면, 'AAABC'를 리턴합니다.
create or replace function next_depth(str varchar2)
return varchar2
as
v_str1 varchar2(32767);
v_str2 varchar2(32767);
begin
v_str1 := substr(str, 1, length(str)-1);
v_str2 := substr(str, -1, 1);
return v_str1||chr(ascii(v_str2)+1);
end;
/
create index qnaboard_grp_seq on qnaboard(grp desc, depth asc);
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
첫번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '안녕하세요', null, '길동', sysdate, qnaboard_no_seq.currval, 'A');
두번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '날씨가 맑습니다', null, '철수', sysdate, qnaboard_no_seq.currval, 'A');
세번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '모임이 있습니다', null, '영희', sysdate, qnaboard_no_seq.currval, 'A');
네번째 게시물 입력 - 첫번째 게시물의 답글
답글이 올라오는 경우에는 답글에 부여 할 depth를 결정해야 합니다.
이를 위해서, 부모글의 depth인 'A'로 다음과 같은 쿼리를 실행합니다.
select next_depth(max(depth))
from qnaboard
where grp=1
and depth like 'A_';
위의 쿼리가 null이면 답글에 부여 할 depth는 부모글의 depth에 'A'를 붙인 문자열이 됩니다.
insert into qnaboard
values(qnaboard_no_seq.nextval, '반가워요', null, '만수', sysdate, 1, 'AA');
다섯번째 게시물 입력 - 네번째 게시물의 답글
네번째 게시물의 depth는 'AA'입니다.
select next_depth(max(depth))
from qnaboard
where grp=1
and depth like 'AA_';
위의 쿼리가 null이므로 답글에 부여 할 depth는 부모글의 depth에 'A'를 붙인 'AAA'가 됩니다.
insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 'AAA');
여섯번째 게시물 입력 - 첫번째 게시물의 두번째 답글
첫번째 게시물의 depth는 'A'입니다.
select next_depth(max(depth))
from qnaboard
where grp=1
and depth like 'A_';
위의 쿼리 리턴값 'AB'가 답글에 부여 할 depth가 됩니다.
insert into qnaboard
values(qnaboard_no_seq.nextval, '환영합니다', null, '찬호', sysdate, 1, 'AB');
일곱번째 게시물 입력 - 여섯번째 게시물의 답글
여섯번째 게시물의 depth는 'AB'입니다.
select next_depth(max(depth))
from qnaboard
where grp=1
and depth like 'AB_';
위의 쿼리가 null이므로 답글에 부여 할 depth는 부모글의 depth에 'A'를 붙인 'ABA'가 됩니다.
insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 'ABA');
여덟번째 게시물 입력 - 네번째 게시물의 답글
네번째 게시물의 depth는 'AA'입니다.
select next_depth(max(depth))
from qnaboard
where grp=1
and depth like 'AA_';
위의 쿼리 리턴값 'AAB'가 답글에 부여 할 depth가 됩니다.
insert into qnaboard
values(qnaboard_no_seq.nextval, '저도 방가', null, '병헌', sysdate, 1, 'AAB');
게시판을 검색하는 경우, grp로 내림차순, seq로 오름차순으로 정렬하면 됩니다.
select
case when length(depth)-1=0 then no
when length(depth)-1>0 then null end no
, rpad('+', length(depth)-1, '-')||title title
, writer
, wdate
from qnaboard
order by grp desc, depth;
NO TITLE WRITER WDATE
---------- -------------------- -------------------- -------------------
3 모임이 있습니다 영희 2007-09-15 21:51:26
2 날씨가 맑습니다 철수 2007-09-15 21:51:03
1 안녕하세요 길동 2007-09-15 21:48:23
+반가워요 만수 2007-09-15 21:53:41
+-감사합니다 길동 2007-09-15 21:55:57
+-저도 방가 병헌 2007-09-15 22:03:27
+환영합니다 찬호 2007-09-15 21:57:55
+-감사합니다 길동 2007-09-15 21:59:49