메뉴 건너뛰기

tnt_db

Oracle 최대값과 최소값을 뺀 평균

운영자 2002.09.18 14:22 조회 수 : 4177 추천:15

최대값과 최소값을 뺀 평균
    
조건.
    TEST12 TABLE에 다음과 같은 DATA가 있다.

     STD_ID  TERM  CURR       TEST1 TEST2 TEST3 TEST4 TEST5 UNIT      
     ------- ----- ---------- ----- ----- ----- ----------- ----------
     9701001 19991 공학개론   96    89    86    89    76       2
           .     .        .    .     .     .     .     .     .
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
     9701015 19991 공학개론   82    85    91    85    76       2
     9701001 19991 일반물리학 84    89    84    83    78       2
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
     9701015 19991 일반물리학 70    89    78    85    83       2
     9701001 19991 일반화학   84    79    81    76    83       2
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
     9701015 19991 일반화학   70    77    81    82    82       2
     9701001 19991 전산학개론 59    69    74    91    78       2
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
           .     .        .    .     .     .     .     .     .  
     9701015 19991 전산학개론 45    65    74    90    83       2

     60 행이 선택되었습니다

문제.
    1999년 1학기의 각학생별 과목별 성적이 5번의 시험을 통해
    기록되어 있다.
    각 학생/과목별 로 5번중 최대성적과 최소성적을 뺀 나머지 3개를
    이용해 과목별 평균을 구하고 반올림한후 학점(UNIT)을 곱해 학생별
    총점을 구한뒤 최종적으로 전체학점으로 나눈 학생별 평균을 구하고
    석차를 구하는 SQL을 작성한다.
    결과는 다음과 같다.

    학번    평균       석차      
    ------- ---------- ----------
    9701001      81.75          4
    9701002         82          3
    9701003      80.75          9
    9701004       82.5          2
    9701005      80.25         11
    9701006         83          1
    9701007       80.5         10
    9701008      81.25          7
    9701009         78         15
    9701010         81          8
    9701011         80         12
    9701012      81.75          4
    9701013      79.25         14
    9701014       81.5          6
    9701015         80         12
    15 행이 선택되었습니다

생각.
    석차를 구하는 방법은 별도의 주제로 다루어지고 있다.
    그 주제를 참고하면 그렇게 어려운 문제는 아닌듯하다.
    5개의 성적중 최대값과 최소값을 어떻게 뺄 것인가?.
    최대값과 최소값을 빼면 석차를 구하는법은 알고있다.
    엿보기1.최대값과 동일한값이 있어도 그중 하나만 빼야하고
            최소값과 동일한 값이 있어도 그중 하나만 빼야한다.
            함수중 Greatest,Least 가 있다.
            잘 이용해보자.
    엿보기2.최대값과 최소값을 뺀 나머지 3개를 더해서 3으로 나눈값이
            그학생의 해당학기의 해당과목 학기 점수 이다.
            거기에 학점을 곱하고 다시 그학생이 수강한 전체학점을
            나누면 그학생의 해당학기 총점이된다.
    엿보기3.그렇게 구해진 학생의 평균을 동일한 DATASET과 JOIN을 걸어
            자기보다 평균이 큰 학생의 수를 세고 더하기 1 을 하면
            해당 학생의 석차다.

해법.
    엿보기를 통해 해답은 다 나왔다.
    직접 작성해보자.
    스스로 작성해야 정말 자기것이 되지 않을까?.
    단계1.해당과목의 학기 점수를 구하는 방식은 다음과 같이 하면 될것이다.

         (TEST1+TEST2+TEST3+TEST4+TEST5
        - LEAST(TEST1,TEST2,TEST3,TEST4,TEST5)
        - GREATEST(TEST1,TEST2,TEST3,TEST4,TEST5)
         )/3      
    단계2.최종 GROUP 지을 단위는 학생이므로 학생별로 SUM을한후
          그값을 학생별로 SUM한 총 학점과 나누면 해당학생의평균이다.
    
        SELECT STD_ID 학번,
               SUM(ROUND( (TEST1+TEST2+TEST3+TEST4+TEST5
                         - LEAST(TEST1,TEST2,TEST3,TEST4,TEST5)
                         - GREATEST(TEST1,TEST2,TEST3,TEST4,TEST5)
                          )/3
                        ) * UNIT  
                  ) /   SUM(UNIT)  AVRG
        FROM  TEST12
        WHERE TERM = '19991'
        GROUP BY
              STD_ID
        여기까지의 결과는 다음과 같다.

         학번    AVRG      
         ------- ----------
         9701001      81.75
         9701002         82
         9701003      80.75
         9701004       82.5
         9701005      80.25
         9701006         83
         9701007       80.5
         9701008      81.25
         9701009         78
         9701010         81
         9701011         80
         9701012      81.75
         9701013      79.25
         9701014       81.5
         9701015         80
         15 행이 선택되었습니다

    단계3.이제 마지막으로 뒤에 석차만 붙여주면 된다.
          엿보기에서 언급했듯이 동일 DATASET의 JOIN을 통해
          자신의 점수보다 점수가 높은 사람의 수를 세고 더하기1을한다.

     SELECT A.STD_ID 학번,
            A.AVRG   평균,
            COUNT(B.STD_ID) + 1 석차
     FROM
          ( SELECT STD_ID,
                   SUM(ROUND( (TEST1+TEST2+TEST3+TEST4+TEST5
                            - LEAST(TEST1,TEST2,TEST3,TEST4,TEST5)
                            - GREATEST(TEST1,TEST2,TEST3,TEST4,TEST5)
                              )/3
                            ) * UNIT  
                      ) /   SUM(UNIT)  AVRG
            FROM  TEST12
            WHERE TERM = '19991'
            GROUP BY
                  STD_ID
          ) A,
          ( SELECT STD_ID,
                   SUM(ROUND( (TEST1+TEST2+TEST3+TEST4+TEST5
                             - LEAST(TEST1,TEST2,TEST3,TEST4,TEST5)
                             - GREATEST(TEST1,TEST2,TEST3,TEST4,TEST5)
                              )/3
                            ) * UNIT  
                      ) /   SUM(UNIT)  AVRG
             FROM   TEST12
             WHERE TERM = '19991'
             GROUP BY
                   STD_ID
          ) B
     WHERE B.AVRG(+) > A.AVRG
     GROUP BY
           A.STD_ID,A.AVRG
          최종적인 답이다.
          IN-LINE VIEW A와 B는 동일하다.
          두개의 DATASET A와 B가  
          WHERE B.AVRG(+) > A.AVRG
          와 같은 조건으로 연결되면 DATASET A 하나의 ROW에 자신의
          평균보다 높은 점수를 가지는 ROW가 연결되며,
          우리는 그 숫자만을 세어 1을 더하기위해
          COUNT(B.STD_ID) + 1 와 같이 해주고 석차라고 이름만
          달아주면 된다.
          B 에 (+) 가 달린 이유는 다 알고 있듯이 1등학생은 자신보다
          성적이 좋은 사람이 없으므로 연결될 DATA가 없기 때문이다.

뒷풀이.
    DATABASE 에서 제공되는 함수 외에도
    자신이 만든 함수를 이용해서도 절차형 언어로 길게 풀어줘야할
    많은 부분을 SQL 내로 끌어들일 수 있다.
    RESPONSE TIME은 둘째 치더라도 하나의 SQL로 원하는 DATA를
    읽어와야 될 경우는 많다.
    많은 경우에 대비해 연습해 둔다면, 후에 자신의 응용력을 가미해
    커다란 시간의 절약을 거둘 수 있으리라.
사족.
    초보자,
    KEYBOARD 두드리기 좋아하는사람,
    PROCEDURE에 유난히 애착이 있는사람,
    생각하기를 별로 좋아하지 않는 사람,
    IN-LINE VIEW를 좋아하지 않는사람 등에게는 권하고 싶지 않은 방식이다.
위로