메뉴 건너뛰기

tnt_db

Oracle 중복DATA 찾아내기

운영자 2002.09.17 20:40 조회 수 : 2817 추천:20

다음은 어느학생으로부터 개인적으로 받은 질문입니다.

과목테이블입니다. (과목의 정보입니다.)
create table subject (
sub_num         varchar2(10) primary key,                 --과목번호
sub_name        varchar2(15) not null,                    --과목명
sub_part        number(3) ,                               --영역
time1           varchar2(5),                              --월요일
time2           varchar2(5),                              --화요일
time3           varchar2(5),                              --수요일
time4           varchar2(5),                              --목요일
time5           varchar2(5),                              --금요일
full_student    number(3) not null,                       --총인원
current_student number(3) default 0,                      --현수강신청인원
room_num        varchar2(5),                              --강의실번호
part_num        varchar2(5) not null,                     --분반
part            varchar2(10),                             --과목분류(전선)
grade           number(3),                                --학점
prof_num        number(15),                                --교수번호
major_num       varchar2(10)                              --소속학과
);                                

수강신청테이블입니다. (여기엔 수강신청을 하는 모든 학생의 과목내용이 기록됩니다.)
create table ord (
stu_num         number(15) not null,              --학번
sub_num         varchar2(10) not null,            --과목명
time1           varchar2(5),                      --월요일
time2           varchar2(5),                      --화요일
time3           varchar2(5),                      --수요일
time4           varchar2(5),                      --목요일
time5           varchar2(5),                      --금요일
ord_date        date default sysdate              --신청일
);                                


문제점 : 수강신청을 학생별 과목별로 받을때,
         한 학생이 신청한 과목의 강의시간이 이미 신청한 과목들의 강의시간과
         한시간이라도 중복이 일어나면 check해서 신청을 할 수 없게 하려고
         한다.
         과목테이블과 수강신청테이블의 TIME column 이 해당요일의 강의 시간을
         포함하고 있다.
         예를들어 어떤과목의 강의시간이 월요일 2,3교시와 목요일 5교시라면
         TIME1 column에 '23' ,TIME4 column에 '5'  로 값이 들어가있고,해당
         값을 수강신청시 동일 column에 넣어준다.
         만약 어떤 학생이 월요일 2,3교시에 강의가 있는 A 라는 과목의
         수강신청을 하려고 한다면, 기존에 수강신청된 해당학생의 과목들을
         찾아서 월요일 2,3교시에 이미 강의가 잡혀있는지 CHECK한후
         있으면 신청을 할 수 없게 해야한다.
         TABLE DESIGN에 문제가 있는듯 하지만 다음과 같은 QUERY를 이용해서
         CHECK는 가능합니다.
         the_sub_num,the_stu_num 는 수강신청시 입력된 과목과,학번 입니다.
QUERY :
       SELECT COUNT(*)
       FROM (SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
             FROM  (select 'A'||SUBSTRB(TIME1,NO,1) T1,
                           'B'||SUBSTRB(TIME2,NO,1) T2,
                           'C'||SUBSTRB(TIME3,NO,1) T3,
                           'D'||SUBSTRB(TIME4,NO,1) T4,
                           'E'||SUBSTRB(TIME5,NO,1) T5
                    from   subject,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
                    where  sub_num = the_sub_num),
                   (SELECT ROWNUM RNO  FROM USER_TABLES WHERE ROWNUM <= 5)
             WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
             INTERSECT
             SELECT DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5) ATIME
             FROM  (select 'A'||SUBSTRB(TIME1,NO,1) T1,
                           'B'||SUBSTRB(TIME2,NO,1) T2,
                           'C'||SUBSTRB(TIME3,NO,1) T3,
                           'D'||SUBSTRB(TIME4,NO,1) T4,
                           'E'||SUBSTRB(TIME5,NO,1) T5
                    from   ORD,(SELECT ROWNUM NO FROM USER_TABLES WHERE ROWNUM <= 5)
                    where  sTu_num = the_stu_num),
                   (SELECT ROWNUM RNO  FROM USER_TABLES WHERE ROWNUM <= 5)
             WHERE LENGTHB(DECODE(RNO,1,T1,2,T2,3,T3,4,T4,5,T5)) > 1
            )
설명 : 먼저 각 요일별로 시간이 입력되는 COLUMN의 SIZE 가 5 로 잡혀 있습니다.
       아마 일주일에 5시간을 넘겨서 수업이 들어있는 과목은 없다는 뜻이겠지요.
       더 정확히 얘기하면 하루에 동일과목을 5시간이상 강의하는 과목이 없단 뜻이
       될겁니다.
       해당학번을 가지고 수강신청된 과목을 읽어도 10건은 넘지 않을겁니다.
       마찬가지로 해당 과목코드를 가지고 과목 테이블을 읽으면 정확히 한과목만 나오겠지요.
       두개의 데이터를 가지고 어떻게 지지고 볶아도 RESPONSE TIME은 걱정할 필요가
       없단 얘기지요.
       따라서 먼저 각 요일별로 5자리로 나뉘어 들어있는 시간을 CARTESIAN PRODUCT을
       이용해 월요일은 A,화요일은 B,수요일은 C,목요일은 D,금요일은 E 를 앞에붙여
       한 ROW를 5개의 ROW로 만들고 5개의 ROW의 5개 COLUMN을 다시 CARTESIAN PRODUCT을
       이용해 25개의 ROW로 만들어서 문자뒤에 시간이 붙어있는 DATA만을 걸러냈습니다.
       다른 한테이블도 동일 방식으로 데이타를 걸러낸후 두개를 INTERSECT로 비교해서
       중복되는 데이터의 COUNT를 읽었습니다.
       COUNT가 0보다 크면 이미 중복되는 시간이 존재하고 있다는 뜻이고,
       0이면 강의시간의 중복이 없으니 수강신청이 정상적으로 이루어져도 좋다는
       뜻이 됩니다.


위로