DB/Oracle

Oracle 기간내 그룹의 최근의 값과 이전의 값을 비교하여 변경되었다면 출력하는 쿼리

husks 2023. 9. 5. 09:00
반응형

제목이 좀 기네요. ㅋㅋ

 

최근 업무중에 매월 책이름을 보내줘야 하는 업무가 있었습니다.

 

책아이디와 이름은 매월 쌓이게 되고 책이름은 변경되는 경우도 있습니다.

 

마지막 데이터를 전송하면 받은 업체에서 책이름을 업데이트 하는 업무인데 이전달과 같은 데이터면 굳이 보낼 필요가 없기 때문에 해당 조건을 만족하는 쿼리를 작성하게 되었습니다.

 

해당 쿼리는 아래와 같고 각 라인에 주석처리 되어 있으니 참고해주시기 바랍니다.

SELECT
    BOOK_ID,                -- 도서 ID
    BEFORE_BOOK_NAME,       -- 이전 도서 이름
    LAST_BOOK_NAME,         -- 현재 도서 이름
    CRT_DT                  -- 생성 일자
FROM
    (SELECT
        BOOK_ID,            -- 도서 ID
        CRT_DT,             -- 생성 일자
        LAG(BOOK_NAME) OVER (PARTITION BY BOOK_NAME ORDER BY CRT_DT) AS BEFORE_BOOK_NAME,  -- 이전 도서 이름
        BOOK_NAME AS LAST_BOOK_NAME,  -- 현재 도서 이름
        ROW_NUMBER() OVER (PARTITION BY BOOK_ID ORDER BY CRT_DT DESC) AS rn,  -- 도서 ID 그룹별로 생성 일자 역순으로 순위 부여
        COUNT(*) OVER (PARTITION BY BOOK_ID) AS cnt  -- 도서 ID 그룹별 레코드 수 계산
    FROM
        BOOK_INFO
    WHERE
        CRT_DT BETWEEN TRUNC(ADD_MONTHS(SYSDATE,-6),'MM') AND TRUNC(SYSDATE,'MM')  -- 지난 6개월 동안의 레코드만 선택하며, 도서 이름이 NULL이 아닌 레코드만 검색
    )
WHERE
    ((rn = 1 AND cnt > 1 AND BEFORE_BOOK_NAME <> LAST_BOOK_NAME)  -- 도서 ID 그룹 내에서 가장 최근 레코드이며, 레코드 수가 1보다 크고 이전 도서 이름과 현재 도서 이름이 다른 경우 또는
    (rn = 1 AND cnt = 1))  -- 도서 ID 그룹 내에서 레코드가 하나뿐인 경우
    AND CRT_DT BETWEEN TRUNC(ADD_MONTHS(SYSDATE,-1),'MM') AND TRUNC(SYSDATE,'MM')  -- 현재 월의 첫 날부터 지난 달의 마지막 날까지의 레코드만 선택합니다.
반응형