무한소수의 집계 순서에 따른 결과 값

2021. 4. 2.·Oracle/SQL

무한소수는 집계 순서에 따라 결과 값이 달라질 수 있습니다. 이로 인해 데이터 마이그레이션 이후 데이터 조회 순서가 달라져 쿼리의 결과 값이 달라질 수 있습니다.

 

테스트를 위해 아래의 테이블을 생성하겠습니다.

-- 1
DROP TABLE t1 PURGE;
CREATE TABLE t1 AS SELECT ROWNUM * 100 AS c1 FROM XMLTABLE ('1 to 12');

 

아래 쿼리의 c2 열은 c1 칼럼을 12로 나눠 일부 값이 무한소수로 반환됩니다.

-- 2
SELECT c1, c1 / 12 AS c2 FROM t1;

  C1         C2
---- ----------
 100 8.33333333 -- !
 200 16.6666667 -- !
 300         25
 400 33.3333333 -- !
 500 41.6666667 -- !
 600         50
 700 58.3333333 -- !
 800 66.6666667 -- !
 900         75
1000 83.3333333 -- !
1100 91.6666667 -- !
1200        100

12 행이 선택되었습니다.

 

아래 예제는 t1 테이블을 임의로 정렬하여 집계를 10회 반복 수행합니다. 무한소수 값이 TRUNCATE되어 수행할 때마다 c1 값이 달라지는 것을 확인할 수 있습니다.

-- 3
SET SERVEROUTPUT ON

DECLARE
    v1 NUMBER;
    v2 NUMBER;
BEGIN
    FOR i IN 1 .. 10 LOOP
        SELECT TRUNC (SUM (c1 / 12)) AS c1
             , SUM (c1 / 12) AS c2
          INTO v1
             , v2
          FROM (SELECT   *
                    FROM t1
                   WHERE ROWNUM >= 1
                ORDER BY DBMS_RANDOM.VALUE);

        DBMS_OUTPUT.PUT_LINE (v1 || ', ' || v2);
    END LOOP;
END;
/

649, 649.999999999999999999999999999999999999  -- !
650, 650
650, 650.000000000000000000000000000000000001
650, 650
649, 649.999999999999999999999999999999999999  -- !
650, 650
650, 650.000000000000000000000000000000000001
650, 650
649, 649.999999999999999999999999999999999999  -- !
650, 650

PL/SQL 처리가 정상적으로 완료되었습니다.

 

나눗셈에 의해 무한소수가 발생할 수 있는 표현식에 ROUND 함수를 사용해야 결과 값이 달라지는 현상을 방지할 수 있습니다. 아래 예제는 c1 / 12 표현식 대신 ROUND (c1 / 12, 20) 표현식을 사용합니다. 코드를 반복 수행해도 결과가 변경되지 않는 것을 확인할 수 있습니다.

-- 4
DECLARE
    v1 NUMBER;
    v2 NUMBER;
BEGIN
    FOR i IN 1 .. 10 LOOP
        SELECT TRUNC (SUM (ROUND (c1 / 12, 20))) AS c1
             , SUM (ROUND (c1 / 12, 20)) AS c2
          INTO v1
             , v2
          FROM (SELECT   *
                    FROM t1
                   WHERE ROWNUM >= 1
                ORDER BY DBMS_RANDOM.VALUE);

        DBMS_OUTPUT.PUT_LINE (v1 || ',' || v2);
    END LOOP;
END;
/
650, 650
650, 650
650, 650
650, 650
650, 650
650, 650
650, 650
650, 650
650, 650
650, 650

PL/SQL 처리가 정상적으로 완료되었습니다.
저작자표시 비영리 변경금지 (새창열림)
'Oracle/SQL' 카테고리의 다른 글
  • IF [NOT] EXISTS 절
  • UPDATE 문, DELETE 문에 대한 직접 조인
  • ORA-01779 에러
  • FOR UPDATE SKIP LOCKED 절 사용 방법
정희락
정희락
2007년부터 Oracle Database 성능 최적화에 주력해 왔으며, 현재 한국오라클 Engineered Systems Solution Engineering 팀에서 Solution Engineer로 근무하고 있습니다. 이 블로그는 개인적인 연구 목적으로 운영되며, Oracle 사의 공식 입장을 대변하지 않습니다.
  • 정희락
    TunA
    정희락
  • 전체
    오늘
    어제
    • 분류 전체보기 (199)
      • Oracle (171)
        • SQL (33)
        • PLSQL (10)
        • Performance (74)
        • Administration (37)
        • Installation (3)
        • Utilities (1)
        • JSON (8)
        • Vector (5)
      • Exadata (15)
      • SQL*Plus (2)
      • Linux (5)
      • Resources (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 도서

    • 불친절한 SQL 프로그래밍
    • 불친절한 PL/SQL 프로그래밍
  • 링크

    • Connor McDonald
    • Frits Hoogland
    • Jonathan Lewis
    • Julian Dontcheff
    • Julian Dyke
    • Kun Sun
    • Maria Colgan
    • Martin Bach
    • Mike Dietrich
    • Tanel Poder
  • 공지사항

  • 인기 글

  • 태그

    12c
    19c
    21c
    23ai
    case study
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정희락
무한소수의 집계 순서에 따른 결과 값
상단으로

티스토리툴바