일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 문자열
- 짝수
- StringBuffer
- toLowerCase
- PARSEINT
- string
- substring
- 디비
- 프로시저
- programmers
- 프로그래머스
- 자바
- 오라클
- 1레벨
- Linux
- oracle
- 참조형
- 데이터베이스
- 코테
- 코딩테스트
- Math.min
- SQL
- 1lv
- 배열
- Java
- Integer
- 1단계
- Math.max
- 1level
- 알고리즘
- Today
- Total
웹 프로그래밍
OVER(), PARTITION BY - Oracle 본문
■ OVER()
윈도우 함수중 하나로 집계 함수와 함께 사용하며, group by, order by절을 이용한 복잡한 서브쿼리를 개선할 수 있 는 함수.
또한, OVER() 함수를 사용함으로써 출력되는 칼럼과 그룹화할 칼럼을 일치시켜야 하는 문제점도 개선할 수 있다.
이는 데이터 분석 및 보고서 생성 시 더 유연하고 효율적인 쿼리를 작성하는 데 도움을 준다.
■ PARTITION BY
OVER() 함수 안에 사용할 수 있는 값(분할 기준 절)중 하나로 데이터를 특정 칼럼 값에 따라 그룹으로 나누는 역할.
이를 통해 각 그룹 내에서 집계 함수가 개별적으로 계산되므로, 복잡한 서브쿼리를 사용하지 않고도 다양한 분석을 수행할 수 있다.
■ 예시
※ 예시 하단에 테이블 정보 표기.
1) 직원들의 월급 데이터를 분석하여 각 나이별로 평균 월급을 조회하는 쿼리.
SELECT NAME
, AGE
, SALARY
, DEPT
, ROUND(AVG(SALARY) OVER(PARTITION BY AGE), 0) AS AVG
FROM TB_EMP;
→ 자기 나이에 해당하는 평균 월급을 AVG 칼럼에서 확인할 수 있다.
2) 직원들의 월급 데이터를 분석하여 같은 부서와 등록 날짜 내에서 나이 순서대로 최대 급여를 조회하는 쿼리.
SELECT NAME
, AGE
, SALARY
, DEPT
, REG_DATE
, ROUND(MAX(SALARY) OVER(PARTITION BY DEPT, REG_DATE ORDER BY AGE), 0) AS MAX
FROM TB_EMP;
→ DEPT와 REG_DATE로 그룹화하고, 각 그룹 내에서 나이 순으로 정렬한다.
각 행에의 최대 급여를 MAX 칼럼에서 확인할 수 있다.
※ TB_EMP 테이블 정보
SELECT * FROM TB_EMP ORDER BY SEQ;
■ 마무리
실무에서는 정산 데이터를 다뤘었다. 전일 거래 데이터를 종합하여 매일 정산 데이터가 생기는 배치가 돌고, 월 초에 전월의 최종 정산 데이터를 확인하여 정산하는 구조였는데, 요청 사항은 전월 정산 데이터를 그 다음 달로 이월할 수 있게 하는 것이었다. 요청 사항을 들었을 때 업체별, 정산일별 그룹화 하여 SUM된 금액을 보여주면 된다고 생각하여 간단한 작업이라고 생각했지만 막상 쿼리를 짜는 동안 원하는 쿼리를 짤 수 없었고, 쿼리가 점점 복잡해져 갔다. 여러 삽질 끝에 다행히 이를 해결해 줄 문법이 찾았고 결국 원하는 결과를 얻을 수 있었다. 실무에서 사용한 쿼리를 보여줄 수 없지만... TB_EMP를 이용하여 최대한 비슷하게 예시를 들어보겠다.
SELECT AGE
, DEPT
, SUM(SALARY)
, REG_DATE
, RN
FROM
(SELECT AGE
, DEPT
, SALARY
, REG_DATE
, ROW_NUMBER() OVER(PARTITION BY AGE, DEPT ORDER BY REG_DATE DESC) AS RN
FROM TB_EMP)
WHERE RN = 1
GROUP BY AGE
, DEPT
, REG_DATE
, RN;
→ 위 쿼리는 각 연령대와 부서 내에서 가장 최근 등록 날짜를 가진 직원들이 필터링되고, 그 직원들의 급여가 합산되어 출력된다.
정산금액이 확정된 월말의 데이터만 사용하기 때문에 배치가 실행된 날짜를 기준으로 정렬을 했고, 업체별, 정산일별 금액이 계산되게끔 쿼리를 짰다.
처음부터 위 내용을 인지한 상태로 쿼리를 짰으면 원하는 결과의 쿼리를 구현하는데 조금 덜한 노력과 시간이 들었을 것이다. 모르는 상태로 원하는 결과를 얻겠다고 여러 번 삽질하고 내 능력의 부족함에 스트레스를 받았다.
어려분은 이 문법을 통해 더 간략하고 좋은 쿼리를 짜길 바란다.
'DB(SQL) > oracle' 카테고리의 다른 글
상위 데이터 조회(Rownum, Top) - Oracle, Mssql (0) | 2023.02.23 |
---|---|
컬럼 추가, 삭제, 수정, 변경(ALTER) - Oracle (0) | 2023.02.09 |
시퀀스(SEQUENCE) - Oracle (0) | 2023.02.05 |
트리거(TRIGGER) - ORACLE DB (0) | 2021.09.28 |
프로시저(Procedure), 함수 - ORACLE DB (0) | 2021.09.28 |