SELECT 시에는 꼭 필요한 column 만 불러오기

많은 필드를 불러 올수록 DB는 더 많은 로드를 부담하게 되기 때문에 꼭 필요한 열만 물러오도록 한다.

  -- WORST
  SELECT * FROM TABLE;
  -- BETTER
  SELECT COLUMN1, COLUMN2, COLUMN4, COLUMN8 FROM TABLE;

WHERE절에서 연산을 걸지 않는다.

연산이 들어가게 되면 TABLE FULL SCAN을 하면서 모든 값을 탐색, 계산 한 뒤 조건 충족 여부를 판단하기 때문에 좋지 않다.

  -- WORST
  SELECT COLUMN1, COLUMN4
  FROM TABLE
  WHERE FLOOR(COLUMN4) = 2;
  -- BETTER
  SELECT COLUMN1, COLUMN4
  FROM TABLE
  WHERE COLUMN4 BETWEEN 4 AND 5;

LIKE 조회시 와일드카드 % 는 가급적 뒤에만 붙이자

COLUMN6 LIKE %DF 는 TABLE FULL SCAN을 유발한다.
COLUMN5 IN ('ASDF', 'ERDF'), COLUMN5 = 'ASDF' OR COLUMN5 = 'ERDF' 같은 형태가 낫다.

SELECT DISTINCT, UNION ALL 과 같이 중복을 제거하는 연산은 자제한다

중복을 제거하는 연산은 시간이 많이 걸린다. 불가피하게 사용해야 할 경우 EXISTS, GROUP BY를 활용하는게 낫다.
DISTINCT는 원하는 컬럼에 대해서 중복을 제거하는 것이 아니라 SELECT 해온 모든 ROW에서 중복을 제거하므로 속도가 느려진다.

같은 내용의 조건이라면 GROUP BY 연산의 HAVING 보다는 WHERE 절을 사용하는 것이 좋다

쿼리 실행 순서에서 WHERE 절이 HAVING 절 보다 먼저 실행된다. 따라서 WHERE 절로 미리 데이터를 작게 만들면 GROUP BY 절에서 다뤄야 하는 데이터 크기가 작기 때문에 효율적인 연산이 가능하다.

VIEW VS MVIEW (MATERIALIZED VIEW)

뷰는 질의 할때마다 해당 쿼리를 재 실행하는 것과 같음. 속도가 느림. 다만 데이터는 LIVE 함.
MVIEW는 세팅을 어떻게 하느냐에 따라 질의 할 쿼리를 재사용하여 가져옴. 스냅샷 처럼 이전에 만들어 놓은 엠뷰 테이블에서 데이터를 가져옴.
비용이 많이 들어가고 데이터가 고정적인 경우 엠뷰를 만들어서 사용하는게 좋음. 인덱스도 생성 가능.
리프레시 타임이 많이 드는 경우 데이터가 LIVE하지 않은 문제가 있음.

CHAR VS VARCHAR

4byte 이하는 CHAR, 그 이상은 VARCHAR가 나음.

  • CHAR : 고정 길이 문자열
  • VARCHAR : 가변 길이 문자열

BLOB VS TEXT

많은 양의 데이터 저장, 디폴트 값 지정 안됨, 문자열 뒷부분 공백 제거 안되는 공통점이 있음.
차이점으로 BLOB은 대소문자를 구분, TEXT는 구분 안함.

PRIMARY KEY, UNIQUE KEY

PK와 Unique Key는 자동으로 인덱스가 생성됨.

쿼리 실행 순서

SUB-QUERY -> MAIN-QUERY

INNER JOIN시 테이블 배치 순서

3개 이상의 테이블을 INNER JOIN을 할 때는 크기가 가장 큰 테이블을 FROM 절에 배치하고 INNER JOIN 절에 남은 테이블을 작은 순서대로 배치하는 것이 좋다.
테이블 한두개차이는 상관 없지만 많은 테이블을 JOIN 할 경우 JOIN의 경우의 수가 생기고 OPTIMIZER가 PLANNING을 하면서 비용이 증가된다.

실행 계획 type이 index라면 한 번 더 살펴보기

EXPLAIN으로 실행 계획을 확인 했을 때 type이 index인 부분이 있다. where 절 조건문에서 사용하는 테이블의 컬럼에 인덱스가 제대로 걸려있지 않기 때문에 TABLE FULL SCAN을 한다.
해당 테이블에 index를 걸고 다시 실행 계획을 INDEX RANGE SCAN으로 변경되었고 실제 실행 속도가 1/4로 줄었다. 아래는 type의 종류로 성능이 낮은 것 부터 높은 순으로 정렬했다.

  • ALL : 테이블을 처음부터 끝까지 탐색하여 데이터를 찾음 (TABLE FULL SCAN)
  • INDEX : 인덱스를 처음부터 끝까지 탐색하여 데이터를 찾는 방식 (INDEX FULL SCAN)
  • RANGE : 특정 범위 내에서 인덱스를 사용하여 원하는 데이터를 추출, 데이터가 방대하지 않다면 준수함. (INDEX RANGE SCAN)
  • REF : 조인 할 때 Primary Key 혹은 Unique Key 가 아닌 Key로 매칭 한 경우
  • EQ_REF : 조인 할 때 Primary Key로 매칭
728x90
반응형
-- 락 걸린 테이블 확인
SELECT
    DO.OBJECT_NAME
  , DO.OWNER
  , DO.OBJECT_TYPE
  , DO.OWNER
  , VO.XIDUSN
  , VO.SESSION_ID
  , VO.LOCKED_MODE
FROM
    V$LOCKED_OBJECT VO
  , DBA_OBJECTS DO
WHERE VO.OBJECT_ID = DO.OBJECT_ID
;


-- 해당 테이블에 락이 걸렸는지 확인
SELECT
  A.SID
  , A.SERIAL#
  , B.TYPE
  , C.OBJECT_NAME
FROM
    V$SESSION A
  , V$LOCK B
  , DBA_OBJECTS C
WHERE A.SID = B.SID
  AND B.ID1 = C.OBJECT_ID
  AND B.TYPE='TM'
  AND C.OBJECT_NAME IN (${위 쿼리에서 가져온 OBJECT_NAME});


-- 락 발생 사용자, SQL, OBJECT 조회
SELECT
  DISTINCT X.SESSION_ID
  , A.SERIAL#
  , D.OBJECT_NAME
  , A.MACHINE
  , A.TERMINAL
  , A.PROGRAM
  , B.ADDRESS
  , B.PIECE
  , B.SQL_TEXT
FROM
    V$LOCKED_OBJECT X
  , V$SESSION A
  , V$SQLTEXT B
  , DBA_OBJECTS D
WHERE X.SESSION_ID = A.SID
  AND X.OBJECT_ID = D.OBJECT_ID
  AND A.SQL_ADDRESS = B.ADDRESS 
ORDER BY B.ADDRESS, B.PIECE;


-- 현재 접속자의 SQL 확인 
SELECT
    DISTINCT A.SID
  , A.SERIAL#
  , A.MACHINE
  , A.TERMINAL
  , A.PROGRAM
  , B.ADDRESS
  , B.PIECE
  , B.SQL_TEXT
FROM
    V$SESSION A
  , V$SQLTEXT B
WHERE A.SQL_ADDRESS = B.ADDRESS
ORDER BY A.SID, A.SERIAL#, B.ADDRESS, B.PIECE;


-- 락 세션 죽이기위한 sid 와 serial
SELECT
    A.SID
  , A.SERIAL#
  , A.SID || ', ' || A.SERIAL#
FROM
    V$SESSION A
  , V$LOCK B
  , DBA_OBJECTS C
WHERE A.SID = B.SID
  AND B.ID1 = C.OBJECT_ID
  AND B.TYPE = 'TM'
-- AND C.OBJECT_NAME IN ('${락 걸린 테이블 명}');


-- 해당 세선 kill
SELECT
    DISTINCT X.SESSION_ID
  , A.SERIAL#
  , D.OBJECT_NAME
  , A.MACHINE
  , A.TERMINAL
  , A.PROGRAM
  , A.LOGON_TIME
  , 'ALTER SYSTEM KILL SESSION '''||A.SID||', '||A.SERIAL#||''';'
FROM
    GV$LOCKED_OBJECT X
  , GV$SESSION A
  , DBA_OBJECTS D
WHERE X.SESSION_ID = A.SID
  AND X.OBJECT_ID = D.OBJECT_ID
ORDER BY LOGON_TIME
;


-- 최근 실행된 쿼리 찾기
SELECT 
    SQL_FULLTEXT
  , SQL_ID
  , PARSING_SCHEMA_NAME
  , SERVICE
  , MODULE
  , FIRST_LOAD_TIME
  , LAST_LOAD_TIME
FROM V$SQL
WHERE 1 = 1
  AND PARSING_SCHEMA_NAME = '${스키마 명}'
  AND SERVICE = '${서비스 명}'
ORDER BY LAST_LOAD_TIME DESC
;


-- 최근 실행된 쿼리에 바인팅 변수 찾기
SELECT
    NAME
  , POSITION
  , DATATYPE_STRING
  , VALUE_STRING 
FROM V$SQL_BIND_CAPTURE
WHERE 1=1
  AND SQL_ID = '${위 쿼리에서 가져온 SQL_ID}'
;

SELECT * FROM V$SQL;

SELECT 
  last_active_time
  ,parsing_schema_name
  ,sql_text 
FROM v$sqlarea
WHERE 
  parsing_schema_name <> 'SYS'
  AND parsing_schema_name <> 'SYSMAN'
  AND parsing_schema_name <> 'DBSNMP'
  AND parsing_schema_name <> 'MDSYS'
  AND parsing_schema_name <> 'EXFSYS'
ORDER BY 
  last_active_time DESC;

 

 

안타깝게도 어떤 쿼리가 락을 걸었는지는 알기 쉽지 않다.

특히나 Oracle DB S/W update를 주기적으로 하지 않는다면 유지보수가 쉽지 않다.

728x90
반응형

인덱스 리빌드

DB의 쿼리 수행 속도 저하의 문제 중 하나는 쿼리 튜닝이 문제일 수도 있지만, 인덱스의 밸런스가 깨졌을 경우의 가능성도 있다.
인덱스 밸런스가 깨졌다는게 무슨 의미냐 하면,
DB는 ArrayList와 트리를 합쳐 놓은 구조와 비슷한 B+트리 구조인데, 트리 아래의 데이터들이 무작위로 수정되거나 삭제 되었을 경우 트리 구조가 불균형을 이루게 된다.

이런 경우 인덱스를 재구성 해주면 쿼리 수행 속도를 향상 시킬 수 있다.
(물론 튜닝이 잘 된 쿼리를 짜는게 중요하다.)

오라클의 인덱스 재설정 쿼리는 ALTER INDEX 인덱스명 REBUILD;이고,
인덱스 명을 조회하는 쿼리는 SELECT INDEX_NAME FROM USER_INDEXED;이다.
그리고 인덱스의 데이터 타입이 LOB이라면 인덱스 리빌드는 불가능 하다.

따라서 이 두 쿼리를 조합하고, 조건을 추가하면 리빌드 하는 쿼리는 다음과 같다.

SELECT 'ALTER INDEX ' || INDEX_NAME || ' REBUILD ;'
FROM USER_INDEXES
WHERE INDEX_TYPE != 'LOB'
;

경험상 CUBRID나 TIBERO 도 동일했던 것 같다.

참고 : https://docs.oracle.com/database/121/SPATL/alter-index-rebuild.htm#SPATL1017

 
 
728x90
반응형

계층형 쿼리

개발을 하다보면 메뉴구성, 조직도 등 같은 테이블 내에서 계층적으로 데이터를 처리해야 하는 경우가 많다.
자주 사용 되기도 하고, 이번 프로젝트에서 이 부분에 대한 삽질을 많이 했기 때문에 정리를 해본다.
계층형(hirarchical) 구조는 계급적, 수직적인 관계로 2진 트리 관계라고 할 수 있다.
실습은 Oracle emp 를 이용하며 설치 여건이 안되므로 livesql를 이용한다.
사용법은 여기서 보면 된다.

계층 구조와 용어

(계층 구조와 용어 이미지 만들어 올리기.)

  • 노드 (node) : 테이블 상의 각각의 row를 노드라고 한다.
  • 루트 (root) : 트리 구조의 최상위에 있는 노드를 의미한다.
  • 부모 (parent) : 부모노드. 트리 구조에서 상위에 있는 노드를 부모라고 한다.
  • 자식 (child) : 자식노드. 트리 구조에서 하위에 있는 노드를 자식이라고 한다.
  • 리프 (leaf) : 리프노드 혹은 말단노드. 하위에 연결된 노드가 없는, 자식이 없는 노드이다.
  • 레벨 (level) : 트리구조에서 각각의 계층을 의미한다. 루트부터 순차적으로 1씩 올라간다.

SELF JOIN

테이블 개수가 1개이며 각 ROW가 상위 코드로 부모 자식 관계로 연결 되어 셀프 조인을 사용한다.
최상단 노드의 경우 상위 코드가 NULL 이므로 외부 조인도 사용한다.

SELECT
    C.ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)

결과

ENAME   EMPNO  MGR_NN
- - - - - - - - - - - -
BLAKE   7698    KING
CLARK   7782    KING
JONES   7566    KING
ALLEN   7499    BLAKE
WARD    7521    BLAKE
MARTIN  7654    BLAKE
TURNER  7844    BLAKE
JAMES   7900    BLAKE
MILLER  7934    CLARK
SCOTT   7788    JONES
FORD    7902    JONES
ADAMS   7876    SCOTT
SMITH   7369    FORD
KING    7839     - 

동일한 테이블 EMP 를 각각 C, P 로별칭을 주어 셀프 조인 하였고,
C가 하위 ROW, P가 상위 ROW임을 알 수 있다.
계층적인 결과가 나왔지만, 계층형 구조(TREE)와는 다른 결과이다.


START WITH & CONNECT BY

START WITH ... CONNECT BY 절은 계층형 정보를 표현하기 위한 목적으로 나온 조건이다.

문법

SELECT
    [컬럼 ...]
FROM
    테이블
START WITH [최상위 조건]
CONNECT BY [NOCYCLE] [PRIOR] [계층 구조 조건];

예제

SELECT
    C.ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY PRIOR C.EMPNO = C.MGR

결과

ENAME   EMPNO  MGR_NN
- - - - - - - - - - - -
KING    7839     - 
JONES   7566    KING
SCOTT   7788    JONES
ADAMS   7876    SCOTT
FORD    7902    JONES
SMITH   7369    FORD
BLAKE   7698    KING
ALLEN   7499    BLAKE
WARD    7521    BLAKE
MARTIN  7654    BLAKE
TURNER  7844    BLAKE
JAMES   7900    BLAKE
CLARK   7782    KING
MILLER  7934    CLARK

PRIOR 키워드는 이전 결과의 컬럼을 참조하는 키워드로 현재 행의 MGR을 이전 행의 ENPNO와 연결한다는 의미이다.


LEVEL

계층 레벨(depth level)을 나타낸다.

SELECT
    C.ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
    , LEVEL
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY PRIOR C.EMPNO = C.MGR;
ENAME  EMPNO  MGR_NN  LEVEL
- - - - - - - - - - - - - - -
KING    7839     -      1
JONES   7566    KING    2
SCOTT   7788    JONES   3
ADAMS   7876    SCOTT   4
FORD    7902    JONES   3
SMITH   7369    FORD    4
BLAKE   7698    KING    2
ALLEN   7499    BLAKE   3
WARD    7521    BLAKE   3
MARTIN  7654    BLAKE   3
TURNER  7844    BLAKE   3
JAMES   7900    BLAKE   3
CLARK   7782    KING    2
MILLER  7934    CLARK   3

레벨별로 들여쓰기를 하면 쿼리 결과 볼때 편하다.

SELECT
    LPAD( ' ', 2 * (LEVEL - 1 ) ) || C.ENAME AS ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
    , LEVEL
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY PRIOR C.EMPNO = C.MGR;
ENAME       EMPNO  MGR_NN  LEVEL
- - - - - - - - - - - - - - - - -
KING         7839   -        1
  JONES      7566  KING      2
    SCOTT    7788  JONES     3
      ADAMS  7876  SCOTT     4
    FORD     7902  JONES     3
      SMITH  7369  FORD      4
  BLAKE      7698  KING      2
    ALLEN    7499  BLAKE     3
    WARD     7521  BLAKE     3
    MARTIN   7654  BLAKE     3
    TURNER   7844  BLAKE     3
    JAMES    7900  BLAKE     3
  CLARK      7782  KING      2
    MILLER   7934  CLARK     3

ORDER SIBLINGS BY

계층형 쿼리에서 ORDER BY 절을 사용하면 계층의 상관 관계가가 유지되지 않은체 정렬이 되어 버린다.
이 문제로 한참 삽질을 했었는데, ORDER SIBLINGS BY를 사용하면 계층 구조를 유지하면서 정렬을 할 수 있다.

일반 ORDER BY를 사용했을 경우

SELECT
    LPAD( ' ', 2 * (LEVEL - 1 ) ) || C.ENAME AS ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY NOCYCLE PRIOR C.EMPNO = C.MGR
ORDER BY EMPNO;
ENAME         EMPNO  MGR_NN
- - - - - - - - - - - - - - -
      SMITH   7369    FORD
    ALLEN     7499    BLAKE
    WARD      7521    BLAKE
  JONES       7566    KING
    MARTIN    7654    BLAKE
  BLAKE       7698    KING
  CLARK       7782    KING
    SCOTT     7788    JONES
KING          7839     - 
    TURNER    7844    BLAKE
      ADAMS   7876    SCOTT
    JAMES     7900    BLAKE
    FORD      7902    JONES
    MILLER    7934    CLARK

ORDER SIBLINGS BY를 할 경우

SELECT
    C.ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY NOCYCLE PRIOR C.EMPNO = C.MGR
ORDER SIBLINGS BY EMPNO;
ENAME         EMPNO  MGR_NN
- - - - - - - - - - - - - - -
KING          7839   - 
  JONES       7566  KING
    SCOTT     7788  JONES
      ADAMS   7876  SCOTT
    FORD      7902  JONES
      SMITH   7369  FORD
  BLAKE       7698  KING
    ALLEN     7499  BLAKE
    WARD      7521  BLAKE
    MARTIN    7654  BLAKE
    TURNER    7844  BLAKE
    JAMES     7900  BLAKE
  CLARK       7782  KING
    MILLER    7934  CLARK

CONNECT_BY_ISLEAF

계층 구조에서 ROW의 최하위 레벨 여부의 반환이다.
해당 ROW가 말단 노드라면 1 아니라면 0을 반환한다.

SELECT
    LPAD( ' ', 2 * (LEVEL - 1 ) ) || C.ENAME AS ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
    , CONNECT_BY_ISLEAF LEAF
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY NOCYCLE PRIOR C.EMPNO = C.MGR
ORDER SIBLINGS BY EMPNO;
ENAME        EMPNO  MGR_NN  LEAF
- - - - - - - - - - - - - - - - -
KING          7839   -        0
  JONES       7566  KING      0
    SCOTT     7788  JONES     0
      ADAMS   7876  SCOTT     1
    FORD      7902  JONES     0
      SMITH   7369  FORD      1
  BLAKE       7698  KING      0
    ALLEN     7499  BLAKE     1
    WARD      7521  BLAKE     1
    MARTIN    7654  BLAKE     1
    TURNER    7844  BLAKE     1
    JAMES     7900  BLAKE     1
  CLARK       7782  KING      0
    MILLER    7934  CLARK     1

CONNECT_BY_ROOT

계층구조 쿼리에서 LEVEL이 0인 최상위 로우의 정보를 얻어 올 수 있다.

SELECT
    LPAD( ' ', 2 * (LEVEL - 1 ) ) || C.ENAME AS ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
    , CONNECT_BY_ROOT C.ENAME ROOTNANME
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY NOCYCLE PRIOR C.EMPNO = C.MGR
ORDER SIBLINGS BY EMPNO;
ENAME        EMPNO  MGR_NN  ROOTNANME
- - - - - - - - - - - - - - - - - - - -
KING          7839   -        KING
  JONES       7566  KING      KING
    SCOTT     7788  JONES     KING
      ADAMS   7876  SCOTT     KING
    FORD      7902  JONES     KING
      SMITH   7369  FORD      KING
  BLAKE       7698  KING      KING
    ALLEN     7499  BLAKE     KING
    WARD      7521  BLAKE     KING
    MARTIN    7654  BLAKE     KING
    TURNER    7844  BLAKE     KING
    JAMES     7900  BLAKE     KING
  CLARK       7782  KING      KING
    MILLER    7934  CLARK     KING

SYS_CONNECT_BY_PATH

계층 구조에서 ROOT노드부터 현제 노드까지의 PATH 정보를 가져올 수 있다.

SELECT
    LPAD( ' ', 2 * (LEVEL - 1 ) ) || C.ENAME AS ENAME
    , C.EMPNO
    , P.ENAME AS MGR_NN
    , SYS_CONNECT_BY_PATH( C.ENAME, '/') PATH
FROM
    SCOTT.EMP C
INNER JOIN
    SCOTT.EMP P
ON
    C.MGR = P.EMPNO(+)
START WITH C.MGR IS NULL
CONNECT BY NOCYCLE PRIOR C.EMPNO = C.MGR
ORDER SIBLINGS BY EMPNO;
ENAME         EMPNO  MGR_NN  PATH
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
KING          7839     -      /KING
  JONES       7566    KING    /KING/JONES
    SCOTT     7788    JONES   /KING/JONES/SCOTT
      ADAMS   7876    SCOTT   /KING/JONES/SCOTT/ADAMS
    FORD      7902    JONES   /KING/JONES/FORD
      SMITH   7369    FORD    /KING/JONES/FORD/SMITH
  BLAKE       7698    KING    /KING/BLAKE
    ALLEN     7499    BLAKE   /KING/BLAKE/ALLEN
    WARD      7521    BLAKE   /KING/BLAKE/WARD
    MARTIN    7654    BLAKE   /KING/BLAKE/MARTIN
    TURNER    7844    BLAKE   /KING/BLAKE/TURNER
    JAMES     7900    BLAKE   /KING/BLAKE/JAMES
  CLARK       7782    KING    /KING/CLARK
    MILLER    7934    CLARK   /KING/CLARK/MILLER
728x90
반응형

'Database' 카테고리의 다른 글

[DB] INDEX REBUILD  (0) 2021.01.07
[DBeaver - cubrid] DBeaver Cubrid UTF-8 문제  (1) 2020.12.07
[MongoDB] 설치하기 (MacOS)  (0) 2020.05.18
[SQL] TIMESTAMP TO MILLIS  (0) 2020.04.09
[PostgreSQL] 랜섬웨어  (0) 2020.03.03

FUNCTION

DB에서 제공하는 미리 정의 된 기능.

  • 데이터 값을 계산하거나 조작. (단일 행 함수)
  • 열의 데이터 타입을 변환.
  • 행의 그룹에 대해 계산하거나 요약. (그룹 함수)

DUAL 테이블

쿼리문의 수행 결과가 하나의 ROW로 출력되기 위한 DUMMY 컬럼만 갖고 있음.
함수를 위한 임시 테이블 같은 개념.

단일 행 함수 : 데이터 값을 계산 혹은 조작

  • 각 행에 대해 수행.
  • 데이터 타입에 맞는 함수를 사용 해야 함.
  • 행렬로 하나의 결과를 반환.
  • SELECT, WHERE, ORDER BY 절 등에서 사용 가능.
  • 함수 속의 함수로 중첩해서 사용 가능.

단일 행 함수의 종류.

종류 DESC
문자 타입 문자를 입력받아 문자와 숫자를 반환.
숫자 타입 숫자를 입력받아 숫자를 반환.
날짜 타입 날짜 연산, 날짜 값 반환.
변환 타입 임의의 데이터 타입의 값을 다른 데이터 타입으로 변환.
일반 함수 NVL, DECODE, CASE, WHEN, 순위 함수 등.

문자 처리 함수

     
lower 소문자 반환 lower('fuck DB') = 'fuck db'
upper 대문자 반환 upper('fuck DB') = 'FUCK DB'
initcap 문자열의 첫글자 대문자, 나머지 소문자 initcap('fuck DB') = 'Fuck Db'
substr 문자를 잘라 추출 (한글1byte) substr('Welcome to Oracle',4,3) = 'com' substr('Welcome to Oracle',-4,3) = 'acl'
substrb 문자를 잘라 추출 (한글 2byte) substr('웰컴투오라클',3,4) = 투오라클, substrb('웰컴투오라클’,3,4) = 컴투
concat 문자의 값을 연결 CONCAT('fuck', ' DB')
length 문자의 길이 반환 (한글 1byte) length('오라클’) = 3
lengthb 문자의 길이 반환 (한글 2byte) lengthb('오라클’) = 6
lpad / rpad 입력 받은 문자열과 기호를 정렬하여 특정 길이의 문자열로 반환 "lpad('oracle',10,'#') = '####oracle'"
trim / ltrim / rtrim 잘라내고 남은 문자 표시 rtrim(' oracle ') = ' oracle'trim('a' from 'aaaORACLEaaa') = 'ORACLE'
convert char set으로 변환  
chr ascii 코드 값으로 변환  
ascii ascii 코드값을 문자로 반환 ascii('Oracle')
replace 문자열에서 특정문자 변경  
instr 특정 문자의 위치 반환 instr('Welcome to Oracle', 'o') = 5instr(대상,찾을글자,시작위치,몇번째발견)

숫자 처리 함수

     
round 특정 자릿수에서 반올림. ( -시 정수값도 가능) round(대상,(-)자릿수)
trunc 특정 자릿수에서 버림, 절단.( -시 정수값도 가능) trunc(대상,(-)자릿수)
ceil 올림  
floor 버림  
'' '' ''
abs 절대값 반환  
cos cosine  
exp e의 n승  
floor 소수점 아래를 자름 (버림)  
log log값 반환  
power power(man) m의 n승 반환  
sign sign(n) n<0이면 -1 n=0이면 0,n>0이면 1
sin sine값 반환  
tan tangent값 반환  
mod 입력 받은 수를 나눈 나머지값 반환. mod(대상,2) = 1 (java 에서 %)

날짜 처리 함수

날짜 연산

날짜 연산 DESC 반환값
Date + Number 날짜에 일수를 더한다. Date
Date - Number 날짜에 일수를 뺀다. Date
Date - Date 날짜에서 날짜를 뺀다. 일 수
Date + Number / 24 날짜에 시간을 더할 때는 시간을 24로 나누어서 날짜에 더한다. Date
SELECT
  TO_CHAR( SYSDATE, 'YY/MM/DD/HH24:MI' ),
  SYSDATE + 1,
  SYSDATE - 1,
  (SYSDATE + 1) - (SYSDATE - 7),
  SYSDATE + 13 / 24
FROM
  DUAL;

날짜 처리 함수

MONTH_BETWEEN 함수 외에는 모두 날짜 타입을 반환함.

     
sysdate 시스템상 현재 날짜 반환 sysdate+1 = 내일날짜
months_between 두 날짜 사이가 몇 개월인지 반환 between(date1, date2)
add_months 특정 날짜에 개월수 더함 add_months(date, number)
next_day 특정 날짜에서 최초 요일의 날짜 반환 next_day(date, 요일)sysdate, next_day(sysdate, '수')09.01.17, 09.01.21
last_day 해당 달의 마지막달 반환 last_day(sysdate) = 18.07.31
round 인자로 받은 날짜를 특정 기준으로 반올림 round(date, format)round(hiredate, month) = day < 16 = 이달.01, day > 16 = 담달.01
trunc 인자로 받은 날짜를 특정 기준으로 버림 trunc(date, format)

MONTHS_BETWEEN

두 날짜 사이의 개월 수 계산

  MONTHS_BETWEEN( 날짜, 날짜 )
SELECT
  SYSDATE, hire_date, MONTHS_BETWEEN( SYSDATE, hire_date )
FROM
  employees
WHERE
  department_id = 100;

ADD_MONTHS

월에 날짜 더하기

  ADD_MONTHS( 날짜, 숫자 )
SELECT
  hire_date,
  ADD_MONTHS( hire_date, 3),
  ADD_MONTHS( hire_date, -3)
FROM
  employees
WHERE
  department_id BETWEEN 100 AND 106; 

NEXT_DAY

돌아오는 요일의 날짜 개산하기

  NEXT_DAY( 날자, '요일' or 숫자 )
SELECT
  hire_date,
  NEXT_DAY( hire_date, 'Friday'),
  NEXT_DAY( hire_date, 6)
FROM
  employees
WHERE
  department_id BETWEEN 100 AND 106; 

LAST_DAY

돌아오는 월의 마지막 날짜 계산하기

  LAST_DAY( 날짜 )
SELECT
  hire_date,
  LAST_DAY( hire_date )
FROM
  employees
WHERE
  department_id BETWEEN 100 AND 106; 

ROUND, TRUNC

날짜를 반올림 혹은 절삭

  ROUND or TRUNC ( 날짜, 지정 값[MONTH, YEAR등] )
SELECT
  hire_date,
  ROUND( hire_date, 'MONTH' ),
  ROUND( hire_date, 'YEAR' ),
  TRUNC( hire_date, 'MONTH' ),
  TRUNC( hire_date, 'YEAR' )
FROM
  employees
WHERE
  department_id BETWEEN 100 AND 106; 

형 변환 함수

TO_DATE

날짜를 나타내는 문자열을 명시도니 날짜 형식으로 변환하는 함수

  TO_DATE( 문자열, '지정형식' )
SELECT
  TO_DATE( '20111217', 'YYYYMMDD')
FROM
  DUAL;

TO_NUMBER

숫자 타입의 문자열을 숫자 데이터 타입으로 변환하는 함수. 데이터 타입만 바뀜.

  TO_NUMBER( '숫자' )
SELECT
  TO_NUMBER('1234')
FROM
  DUAL;

TO_CHAR

숫자 값을 지정한 데이터 형식의 문자열로 변환

  TO_CHAR( 숫자 데이터 타입, '지정 형식' )
지정 형식 DESC EX RESULT
9 9로 출력 자릿수 지정 TO_CHAR( 42000, '99999999' ) ' 42000'
0 자릿수 만큼 0을 출력 TO_CHAR( 42000, '09999999' ) 00042000
$ 달러 TO_CHAR( 42000, '$9999999' ) $42000
L 지역 화폐 기호 TO_CHAR( 42000, 'L9999999' ) $42000
, 명시한 위치에 쉼표 TO_CHAR( 42000, '9,999,999' ) 43,000
. 명시한 위치에 소수점 TO_CHAR( 42000, '9999999.99' ) 42000.00

TO_CHAR

날자 값을 지정한 형식의 문자열 타입으로 면환

  TO_CHAR( 날짜 데이터 타입, '지정 형식' )
지정 형식 DESC
CC 세기
YY 연도
YEAR 문자 연도
Q 분기
MM 숫자값 월
MONTH 문자값 월
MON 문자값 약어 월
RM 로마자 월
W 년월의 주
DD 년월주의 일
DAY 요일이름
DY 요일 이름 약어

일반 함수

NVL

  NVL( 열이름, '치환 값' )

NULL 값을 치환 값으로 처리함.

SELECT
  salary * NVL( commission_pct, 1 )
FROM
  employees
ORDER BY
  commission_pct;

NVL2

  NVL2( COLUMN1, COLUMN2, COLUMN3 )

COLUMN1의 값이 NULL이면 COLUMN3를 출력 NULL이라면 COLUMN2를 출력.

DECODE

조건 논리 처리.
3항 연산과 같음.

  DECODE( 열 이름, 조건 값, 치환 값, 기본 값 )
SELECT
  first_name,
  last_name,
  department_id,
  salary as 급여,
  DECODE( department_id, 60, salary * 1.1, salary )   as 조정급여,
  DECODE( department_id, 60, '10%인상', '미인상' )    as 인상여부
FROM
  employees;
ORDER BY
  commission_pct;

CASE

복잡한 조건 논리처리 하기

CASE
  WHEN  조건 1  THEN  출력 값 1
  WHEN  조건 3  THEN  출력 값 2
  ...
  ELSE  출력 값 3
END
SELECT
  employee_id, first_name, last_name, salary,
  CASE
    WHEN salary >= 9000 THEN 'TOP'
    WHEN salary BETWEEN 6000 AND 8999 THEN 'MID'
    ELSE 'LOW'
  END AS salary_grade
FROM
  employees
WHERE
  job_id = 'IT_PROG';

RANK, DENSE_RANK, ROW_NUMBER

데이터 값에 순위 매기기

FUNC DESC EX
RANK 공동 순위를 출력하되, 공동 순위만큼 건너 뛰어 다음 순위 출력. 1, 2, 2, 4, ...
DENSE_RANK 공동 순위를 출력하되, 건너 뛰지 않고 이어서 다음 순위 출력. 1, 2, 2, 3, ...
ROW_NUMBER 공동 순위없이 순위 출력. 1, 2, 3, 4, ...
  RANK () OVER ( [PARTITION BY 열 이름] ORDER BY 열 이름)
SELECT
  employee_id, salary,
  RANK()       OVER( ORDER BY salary DESC ) AS RANK_SALARY,
  DENSE_RANK() OVER( ORDER BY salary DESC ) AS DENSE_RANK_SALARY,
  ROW_NUMBER() OVER( ORDER BY salary DESC ) AS ROW_NUMBER_SALARY
FROM
  employees;
SELECT
  A.employee_id, A.department_id, B.department_name, A.salary,
  RANK()       OVER( PARTITION BY A.department_id ORDER BY salary DESC ) AS RANK_SALARY,
  DENSE_RANK() OVER( PARTITION BY A.department_id ORDER BY salary DESC ) AS DENSE_RANK_SALARY,
  ROW_NUMBER() OVER( PARTITION BY A.department_id ORDER BY salary DESC ) AS ROW_NUMBER_SALARY
FROM
  employees A, departments B
WHERE
  A.department_id = B.department_id
ORDER BY B.department_id, A.salary DESC;

그룹 함수

집계 함수라고도 함.
단일 행 함수와 달리 여러 행에 대해 함수가 적용되어 하나의 결과를 나타내는 함수.
기준 열에 대해 같은 데이터 값 기리 그룹으로 묶고,
묶은 행의 집합에 대해 그룹 함수 연산이 필요하다면 GROUP BY 절을 이용하여 처리할 수 있음.
묶은 그룹에 대해 조건이 필요하다면 HAVING 절을 이용함.

그룹 함수의 사용법

  SELECT  그룹함수( 열 이름 )
  FROM    테이블 이름
  [WHERE 조건식]
  [ORDER BY 열 이름]

주요 그룹 함수

예제 생략

FUNC DESC EX  
count 행 개수를 셈 count(comm) NULL값도 셈
sum 합계 sum(comm)  
avg 그룹의 평균 avg(salary)  
max 그룹의 최댓값 max(salary)  
min 그룹의 최소값 min(salary)  
stddev 그룹의 표준편차    
variance 그룹의 분산    
728x90
반응형

'Database' 카테고리의 다른 글

[SQL] JOIN  (0) 2019.12.27
[SQL] GROUP  (0) 2019.12.26
[SQL] 조건절 WHERE  (0) 2019.12.24
[SQL] 데이터 조회 SELECT  (0) 2019.12.23
DB(Database)란  (0) 2019.12.23

+ Recent posts