[Oracle] 이전 로우 값, 이후 로우 값 가져오는 방법. LAG, LEAD 함수 사용 방법

LAG, LEAD 함수를 통해 이전값, 이후값 가져오기

오라클에서 현재 로우를 기준으로 '이전 로우 값' 또는 '이후 로우 값'을 가져오고 싶으신가요? 해당 방법에 대해 안내해드리려고 합니다. 그렇게 어렵지 않으니 천천히 읽어보세요~ 😘

예시 자료는 <EMP> 테이블에서 'SAL'의 값을 'SAL'로 정렬하여 '이전 값', '이후 값'을 확인해 보려고 합니다. 위의 사진을 보면 다음과 같이 설명할 수 있습니다.

  • 첫 번째 로우 'SAL' 컬럼은 800이며, 이전 로우 값은 없고, 이후 로우 값은 950 입니다. 이전 로우 값이 없는 이유는 첫 번째 행이기 때문입니다.
  • 두 번째 로우 'SAL' 컬럼은 950이며, 이전 로우 값은 800, 이후 로우 값은 1100 입니다.
  • 세 번째 로우 'SAL' 컬럼은 1100이며, 이전 로우 값은 950, 이후 로우 값은 1300 입니다.
  • 마지막 네 번째 로우 컬럼은 'SAL'은 1300이며, 이전 로우 값은 1100 이고, 이후 값은 없습니다. 마지막 행이기 때문이지요.

LAG OVER , LEAD OVER FUNCTION => 이전값, 이후값 가져오기

이번 예제는 매개변수 expr, offset, default 를 보여드리겠습니다. 설명은 아래에 있습니다. 우선 신택스를 확인한 다음 간단한 예제를 보며 마무리 하도록 하겠습니다.

syntax

LAG | LEAD
  { ( expr [, offset [, default]]) [ { RESPECT | IGNORE } NULLS ] 
  | ( expr [ { RESPECT | IGNORE } NULLS ] [, offset [, default]] )
  }
  OVER ([ partition_clause ] order_by_clause)

LAG, LEAD 예제 자료

  SELECT SAL,
         LAG (SAL) OVER (ORDER BY SAL),
         LEAD (SAL) OVER (ORDER BY SAL),
         LAG (SAL, 2) OVER (ORDER BY SAL) LAG_OFFSET_2,
         LAG (SAL, 3, 0) OVER (ORDER BY SAL) LAG_OFFSET_3_DEFAULT_0,
         TA.*
    FROM EMP TA
   WHERE JOB = 'CLERK'
ORDER BY TA.SAL
  • LAG (SAL) OVER (ORDER BY SAL) : 이전값
  • LEAD (SAL) OVER (ORDER BY SAL) : 이후값
  • LAG (SAL, 2) OVER (ORDER BY SAL) : 2번 째 이전값(2번 째 매개변수의 기본값은 1인데 2로 설정해 보았습니다.)
  • LAG (SAL, 3, 0) OVER (ORDER BY SAL) : 3번 째 이전값(2번 째 매개변수 3), 해당 window function 의 scope를 벗어난 경우 0(3번 째 매개변수)을 설정합니다. 3번 째 매개변수의 기본값은 NULL 입니다.

오라클 데이터베이스에서 현재 로우를 기준으로 이전 로우의 값, 또는 이후 로우의 값을 가져오고 싶을 때가 있을 것입니다. 이때 사용할 수 있는 함수가 LAG, LEAD인데요. 해당 함수를 사용하여 어떻게 이전, 이후 로우 값을 가져올 수 있는지 방법에 대해 알아보도록 하겠습니다.

이전 로우 값, 이후 로우 값

예제 테이블은 다음과 같으며 총 14개의 로우를 가지고 있는 사원정보 테이블입니다. 입사일자(HIREDATE) 컬럼을 기준으로 해당 사원보다 이전에 입사한 직원, 그리고 이후에 입사한 직원 정보를 알아보도록 하겠습니다.

SELECT * FROM EMP;

     EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
      7698 BLAKE                MANAGER                  7839 91/01/05       2850                    30
      7782 CLARK                MANAGER                  7839 99/09/06       2450                    10
      7566 JONES                MANAGER                  7839 01/02/04       2975                    20
      7788 SCOTT                ANALYST                  7566 03/06/17       3000                    20
      7902 FORD                 ANALYST                  7566 81/03/12       3000                    20
      7369 SMITH                CLERK                    7902 07/12/01        800                    20
      7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
      7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
      7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30
      7844 TURNER               SALESMAN                 7698 81/08/09       1500          0         30
      7876 ADAMS                CLERK                    7788 87/05/23       1100                    20
      7900 JAMES                CLERK                    7698 81/03/12        950                    30
      7934 MILLER               CLERK                    7782 03/01/23       1300                    10
      7839 KING                 PRESIDENT                     96/11/17       5000                    10

14 rows selected.

LAG, LEAD 함수 사용 방법

LAG 함수는 이전 로우 값, LEAD 함수는 이후 로우 값을 가져오는 오라클 분석 함수입니다. 특히 셀프조인을 굳이 할 필요 없이, 컬럼에 함수를 사용하는 것만으로 바로 조회가 가능하기 때문에 알아두면 유용한 함수랍니다.

함수의 가장 기본적인 사용 방법은 첫 번째 매개변수에 이전, 이후 값을 가져오고 싶은 컬럼을 지정하고 OVER 절에 어떠한 순서에서 가지고 올지 정하는 것입니다. 이 부분을 먼저 살펴보도록 하겠습니다.

LAG, LEAD 기본 문법

다음은 입사일자를 기준으로 이전 로우값, 이후 로우값을 가져오는 예제입니다. 조회 결과의 특징은 HIREDATE가 '1981-03-12' 동일한 JAMES와 FORD의 경우, 이전값과 이후값이 예상과 다르게 가져올 수도 있다는 것입니다. 그리하여 LAG와 LEAD 함수를 사용할 때에는 키값과 같이 고유하게 지정할 수 있는 컬럼을 순서로 하여 순서가 겹치지 않도록 하는 것이 중요합니다.

SELECT LAG (HIREDATE) OVER (ORDER BY HIREDATE),
              LEAD (HIREDATE) OVER (ORDER BY HIREDATE),
              TA.*
         FROM EMP TA
     ORDER BY HIREDATE;

LAG(HIRE LEAD(HIR      EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
-------- -------- ---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
         81/02/22       7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
81/02/20 81/03/12       7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
81/02/22 81/03/12       7900 JAMES                CLERK                    7698 81/03/12        950                    30
81/03/12 81/08/09       7902 FORD                 ANALYST                  7566 81/03/12       3000                    20
81/03/12 81/09/28       7844 TURNER               SALESMAN                 7698 81/08/09       1500          0         30
81/08/09 91/01/05       7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30
81/09/28 96/11/17       7698 BLAKE                MANAGER                  7839 91/01/05       2850                    30
91/01/05 99/09/06       7839 KING                 PRESIDENT                     96/11/17       5000                    10
96/11/17 01/02/04       7782 CLARK                MANAGER                  7839 99/09/06       2450                    10
99/09/06 03/01/23       7566 JONES                MANAGER                  7839 01/02/04       2975                    20
01/02/04 03/06/17       7934 MILLER               CLERK                    7782 03/01/23       1300                    10
03/01/23 07/12/01       7788 SCOTT                ANALYST                  7566 03/06/17       3000                    20
03/06/17 87/05/23       7369 SMITH                CLERK                    7902 07/12/01        800                    20
07/12/01                7876 ADAMS                CLERK                    7788 87/05/23       1100                    20

14 rows selected.

LAG, LEAD 매개변수 확장

LAG와 LEAD 함수의 매개변수는 크게 3가지이며 다음과 같습니다.

  • value_expr : 첫 번째 매개변수는 조회하려는 컬럼 또는 표현이며, 필수 매개변수입니다.
  • offset : 두 번째 매개변수는 몇 단계 이전, 이후 값을 가져올지 설정합니다. 생략하면 기본값은 1이기에 바로 이전, 이후 값을 조회합니다.
  • default : 세 번째 매개변수는 윈도우를 벗어난 최초값 또는 최종값일 때 반환할 값을 지정합니다. 예를 들면 처음 값과 마지막 값은 이전이나 이후 값이 없기에 기본적으로 null을 반환하는데, null 대신 조회하고 싶은 값을 입력합니다. NVL 함수와 비슷한 기능이랍니다.

offset 매개변수를 활용하여 해당 로우보다 3번 째 이전, 이후 로우 값을 가져와보도록 하는 예제는 다음과 같습니다.

SELECT LAG (HIREDATE, 3) OVER (ORDER BY HIREDATE), TA.*
         FROM EMP TA
     ORDER BY HIREDATE;

LAG(HIRE      EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
-------- ---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
               7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
               7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
               7900 JAMES                CLERK                    7698 81/03/12        950                    30
81/02/20       7902 FORD                 ANALYST                  7566 81/03/12       3000                    20
81/02/22       7844 TURNER               SALESMAN                 7698 81/08/09       1500          0         30
81/03/12       7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30
81/03/12       7698 BLAKE                MANAGER                  7839 91/01/05       2850                    30
81/08/09       7839 KING                 PRESIDENT                     96/11/17       5000                    10
81/09/28       7782 CLARK                MANAGER                  7839 99/09/06       2450                    10
91/01/05       7566 JONES                MANAGER                  7839 01/02/04       2975                    20
96/11/17       7934 MILLER               CLERK                    7782 03/01/23       1300                    10
99/09/06       7788 SCOTT                ANALYST                  7566 03/06/17       3000                    20
01/02/04       7369 SMITH                CLERK                    7902 07/12/01        800                    20
03/01/23       7876 ADAMS                CLERK                    7788 87/05/23       1100                    20

14 rows selected.

default 매개변수를 활용하여, 최초 입사자, 최종 입사자의 이전 이후 값이 없는 경우 값을 표시해 보도록 하는 예제는 다음과 같습니다.

SELECT LAG (HIREDATE, 1, '00010101') OVER (ORDER BY HIREDATE),
              LEAD (HIREDATE, 1, '99991231') OVER (ORDER BY HIREDATE),
              TA.*
         FROM EMP TA
     ORDER BY HIREDATE;

LAG(HIRE LEAD(HIR      EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
-------- -------- ---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
01/01/01 81/02/22       7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
81/02/20 81/03/12       7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
81/02/22 81/03/12       7900 JAMES                CLERK                    7698 81/03/12        950                    30
81/03/12 81/08/09       7902 FORD                 ANALYST                  7566 81/03/12       3000                    20
81/03/12 81/09/28       7844 TURNER               SALESMAN                 7698 81/08/09       1500          0         30
81/08/09 91/01/05       7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30
81/09/28 96/11/17       7698 BLAKE                MANAGER                  7839 91/01/05       2850                    30
91/01/05 99/09/06       7839 KING                 PRESIDENT                     96/11/17       5000                    10
96/11/17 01/02/04       7782 CLARK                MANAGER                  7839 99/09/06       2450                    10
99/09/06 03/01/23       7566 JONES                MANAGER                  7839 01/02/04       2975                    20
01/02/04 03/06/17       7934 MILLER               CLERK                    7782 03/01/23       1300                    10
03/01/23 07/12/01       7788 SCOTT                ANALYST                  7566 03/06/17       3000                    20
03/06/17 87/05/23       7369 SMITH                CLERK                    7902 07/12/01        800                    20
07/12/01 99/12/31       7876 ADAMS                CLERK                    7788 87/05/23       1100                    20

14 rows selected.

LAG, LEAD PARTITION 절 사용하기

LAG 및 LEAD 함수에서 OVER 윈도우 다음에는 다음의 절을 지정할 수 있습니다. ORDER BY 절은 이전, 이후 행을 식별할 수 있으야 하므로 필수 값이며, PARTITION BY 절은 GROUP으로 나누어 이전, 이후 값을 조회할 때 사용하는 선택값입니다.

다음은 JOB별로 이전, 이후 입사일자를 조회해 보는 예제 자료입니다.

SELECT LAG (HIREDATE) OVER (PARTITION BY JOB ORDER BY HIREDATE),
              LEAD (HIREDATE) OVER (PARTITION BY JOB ORDER BY HIREDATE),
              TA.*
         FROM EMP TA
     ORDER BY JOB;

LAG(HIRE LEAD(HIR      EMPNO ENAME                JOB                       MGR HIREDATE        SAL       COMM     DEPTNO
-------- -------- ---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
         03/06/17       7902 FORD                 ANALYST                  7566 81/03/12       3000                    20
81/03/12                7788 SCOTT                ANALYST                  7566 03/06/17       3000                    20
         03/01/23       7900 JAMES                CLERK                    7698 81/03/12        950                    30
81/03/12 07/12/01       7934 MILLER               CLERK                    7782 03/01/23       1300                    10
03/01/23 87/05/23       7369 SMITH                CLERK                    7902 07/12/01        800                    20
07/12/01                7876 ADAMS                CLERK                    7788 87/05/23       1100                    20
         99/09/06       7698 BLAKE                MANAGER                  7839 91/01/05       2850                    30
91/01/05 01/02/04       7782 CLARK                MANAGER                  7839 99/09/06       2450                    10
99/09/06                7566 JONES                MANAGER                  7839 01/02/04       2975                    20
                        7839 KING                 PRESIDENT                     96/11/17       5000                    10
         81/02/22       7499 ALLEN                SALESMAN                 7698 81/02/20       1600        300         30
81/02/20 81/08/09       7521 WARD                 SALESMAN                 7698 81/02/22       1250        500         30
81/02/22 81/09/28       7844 TURNER               SALESMAN                 7698 81/08/09       1500          0         30
81/08/09                7654 MARTIN               SALESMAN                 7698 81/09/28       1250       1400         30

14 rows selected.

이전 로우, 이후 로우, LAG LEAD 함수 실전 예제

오라클 이전 행, 이후 행

'코드', '분류번호', '명칭', '급여구분', '단가', '적용개시일자', '적용종료일자'로 이루어진 로우가 있다고 가정해 봅시다. 특히 적용개시일자와 적용종료일자를 중점적으로 살펴보겠습니다. 특징은 적용종료일자가 무기한이면 '9999-12-31'의 값을 설정하며, 이전 종료일자 바로 다음 날이 그 다음 코드의 적용개시일자라는 것입니다. 이것을 어떻게 실제로 사용할 수 있는지 예제를 통해 간단히 보여드리도록 하겠습니다.

  • 적용개시일자 2023-01-01, 적용종료일자 9999-12-31
  • 적용개시일자 2022-01-01, 적용종료일자 2022-12-31

다음 예제는 개시일자, 종료일자 컬럼이 모두 있는데, 실수로 이전 로우의 종료일자와 해당 로우의 시작일자가 중복되는 문제가 발생하였습니다.

WITH TA
          AS (SELECT 'AA222' AS CODE,
                     4520 AS PRICE,
                     '20221201' AS BEGIN,
                     '99991231' AS END
                FROM DUAL
              UNION ALL
              SELECT 'AA222',
                     4430,
                     '20220101',
                     '20221231'
                FROM DUAL)
     SELECT *
       FROM TA;

CODE            PRICE BEGIN            END
---------- ---------- ---------------- ----------------
AA222            4520 20221201         99991231
AA222            4430 20220101         20221231

다음과 같이 종료일자를 별도의 컬럼으로 설정하지 않고, 이전 로우 값을 통해 계산하도록 하는 예제자료입니다. 이처럼 LAG, LEAD를 활용할 수 있답니다.

WITH TA
          AS (SELECT 'AA222' AS CODE, 4520 AS PRICE, '20230101' AS BEGIN FROM DUAL
              UNION ALL
              SELECT 'AA222', 4430, '20220101' FROM DUAL)
     SELECT CODE,
            BEGIN,
            NVL (
               TO_CHAR (
                  TO_DATE (LEAD (BEGIN) OVER (PARTITION BY CODE ORDER BY BEGIN))
                  - 1,
                  'YYYYMMDD'),
               '99991231')
       FROM TA;

CODE       BEGIN            NVL(TO_CHAR(TO_D
---------- ---------------- ----------------
AA222      20220101         20221231
AA222      20230101         99991231

댓글