HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤩
개발
/데이터베이스(Database)/
Database
Database
/
SQL 기본 및 활용 (1)

SQL 기본 및 활용 (1)

조인의 형태INNER JOINON 절NATURAL JOINUSING 절OUTER JOINCROSS JOIN집합연산자UNION과 UNION ALL의 결과집합계층형 질의와 셀프 조인계층형 질의계층형 SQL에서 제공하는 가상 칼럼SELF JOIN의 활용서브 쿼리서브 쿼리 사용 시 주의점서브 쿼리 사용이 가능한 위치동작 방식에 따른 서브쿼리 분류반환 형태에 따른 서브쿼리 분류EXISTS 문 서브쿼리 사용인라인뷰 서브쿼리HAVING 절의 서브쿼리 사용UPDATE 문의 SET 절에 위치하는 서브쿼리INSERT 문에 사용되는 서브쿼리뷰 사용하기그룹 함수그룹함수의 종류ROLLUP 함수를 이용한 합계 데이터 출력ROLLUP + GROUPING 함수를 이용한 합계 데이터 출력CUBE 함수를 이용한 합계 데이터 출력UNION ALL + GROP BY 를 이용한 합계 데이터 출력DCL(Data Control Language)ROLE을 이용한 권한 부여오라클 DBMS에서 일반적으로 부여하는 ROLEDCL_TEST 계정 제거 및 재생성, 기본 ROLE 부여

조인의 형태

INNER JOIN
INNER JOIN은 join 조건에서 동일한 값이 있는(매칭되는) 행만 반환 동등(EQUI) 조인이라고도 함
NATURAL JOIN
NATURAL JOIN은 두 테이블 간의 동일한 이름을 갖는 모든 칼럼들에 대해 INNER JOIN을 수행함 예를 들어 TB_EMP, TB_DEPT 테이블 모두 DEPT_CD 라는 칼럼이 존재한다면 DEPT_CD 칼럼을 기준으로 INNER JOIN 됨
USING 조건절
NATURAL JOIN 에서는 모든 일치되는 칼럼들에 대해 INNER JOI이 이루어지지만 FROM 절의 USING 조건절을 이용하면 같은 이름을 가진 칼럼들 중에서 원하는 칼럼에 대해서만 선택적으로 INNER JOIN을 할 수가 있다.
ON 조건절
JOIN 서술부(ON 조건절)와 비 JOIN 서술부(WHERE 조건절)를 분리하여 이해가 쉬우며 칼럼명이 다르더라도 JOIN 조건을 사용할 수 있는 장점이 있다.
CROSS JOIN
CROSS JOIN 은 일반집합연산자의 PRODUCT 개념으로, 테이블 간 JOIN 조건이 없는 경우 생길 수 있는 모든 데이터의 조합을 말함
OUTER JOIN(외부 조인)
INNER JOIN과 대비하여 OUTER JOIN이라고 불리며, JOIN 조건에서 동일한 값이 없는 행도 결과집합에 포함시킬 때 사용함

INNER JOIN

테이블 조인 시 조인 조건에 대해서 동일한 값이 있는 행을 리턴

ON 절

ON절을 이용한 조인은 ON절에 조인 조건을 기재할 수 있음. 여러 개의 칼럼에 대한 조인 조건을 기재 가능하며 조인하는 칼럼의 이름이 서로 달라도 조인을 수행할 수 있음. 이러한 특성으로 실무에서 널리 사용되는 조인의 형태
SELECT A.SUBWAY_STATN_NO , A.LN_NM , A.STATN_NM , B.BEGIN_TIME , B.END_TIME , CASE WHEN B.TK_GFF_SE_CD = 'TGS001' THEN '승차' WHEN B.TK_GFF_SE_CD = 'TGS002' THEN '하차' END TK_GFF_SE_NM , B.TK_GFF_CNT FROM TB_SUBWAY_STATN A INNER JOIN TB_SUBWAY_STATN_TK_GFF B ON (A.SUBWAY_STATN_NO = B.SUBWAY_STATN_NO) WHERE A.SUBWAY_STATN_NO = '000001' --1호선 서울역 AND B.STD_YM = '202010' AND B.BEGIN_TIME = '0800' AND B.END_TIME = '0900' ORDER BY B.TK_GFF_CNT DESC;
  • ON절, WHERE절, SELECT절에 존재하는 모든 조인 칼럼에 대해서 앨리어스를 기재해야 함.

NATURAL JOIN

SELECT DEPT_CD , A.DEPT_NM , B.EMP_NO , B.EMP_NM FROM TB_DEPT_6_1_6 A NATURAL JOIN TB_EMP_6_1_6 B ORDER BY DEPT_CD ;
  • TB_DEPT_6_1_6 과 TB_EMP_6_1_6에 둘다 DEPT_CD 컬럼이 존재하여 그 칼럼을 기준으로 NATURAL JOIN을 실시함. SELECT 문에서 A.DEPT_CD, B.DEPT_CD 와 같은 형태로 조회 불가 ⇒ SQL 에러 발생함

USING 절

SELECT SUBWAY_STATN_NO , A.LN_NM , A.STATN_NM , B.BEGIN_TIME , B.END_TIME , CASE WHEN B.TK_GFF_SE_CD = 'TGS001' THEN '승차' WHEN B.TK_GFF_SE_CD = 'TGS002' THEN '하차' END TK_GFF_SE_NM , B.TK_GFF_CNT FROM TB_SUBWAY_STATN A JOIN TB_SUBWAY_STATN_TK_GFF B USING (SUBWAY_STATN_NO) WHERE SUBWAY_STATN_NO = '000001' --1호선 서울역 AND B.STD_YM = '202010' AND B.BEGIN_TIME = '0800' AND B.END_TIME = '0900' ORDER BY B.TK_GFF_CNT DESC ;
  • USING 절에 기재하는 조인 칼럼에는 앨리어스를 붙일 수 없음. A.SUBWAY_STATN_NO, B.SUBWAY_STATN_NO 라고 하면 SQL 문법 에러가 발생
    • 마찬가지로 SELECT 나 WHERE 절에도 앨리어스 사용 못함
 

OUTER JOIN

OUTER JOIN 종류
설명
LEFT OUTER JOIN
FROM 절에 기재한 테이블을 중심으로 왼쪽에 기재한 테이블이 OUTER, 오른쪽에 기재한 테이블이 INNER 왼족에 있는 OUTER 집합을 기준으로 오른쪽에 있는 INNER 집합은 매칭되는 데이터만 출력됨(왼쪽 OUTER는 다 나오고, 오른쪽 INNER는 있는것만 보여줌)
RIGHT OUTER JOIN
오른쪽 OUTER는 다 나오고, 왼쪽 INNER는 있는 것만 보여줌
FULL OUTER JOIN
FROM 절에 기재한 테이블에 대해서 LEFT OUTER JOIN의 결과와 RIGHT OUTER JOIN의 결과, 그리고 INNER JOIN의 결과가 모두 출력된다. 실무에서 데이터 검증 작업을 진행할 때 자주 쓰이고 있는 조인의 형태

CROSS JOIN

SELECT ROWNUM AS RNUM , NVL(A.DEPT_CD, '(Null)') AS A_DEPT_CD , NVL(A.DEPT_NM, '(Null)') AS A_DEPT_NM , NVL(B.EMP_NO , '(Null)') AS B_EMP_NO , NVL(B.EMP_NM , '(Null)') AS B_EMP_NM , NVL(B.DEPT_CD, '(Null)') AS B_DEPT_CD FROM TB_DEPT_6_1_10 A CROSS JOIN TB_EMP_6_1_10 B ORDER BY RNUM;
  • CROSS JOIN을 하면 두 테이블의 데이터의 곱집합의 결과가 나오게 됨. 한 테이블 데이터 5개, 다른 테이블 데이터 9개면 5*9 = 45 개의 결과값이 나오게 됨
  • CROSS JOIN은 특정 테이블의 데이터를 복제할 때 많이 사용함

집합연산자

집합연산자의 종류
설명
UNION
여러 개 SQL 문의 결과에 대한 합집합 중복된 행은 1개의 행으로 출력됨 중복된 행을 1개의 행으로 출력하는 과정에서 정렬이 발생할 수도 있다.
UNION ALL
여러 개 SQL 문의 결과에 대한 합집합 중복된 행도 그대로 결과로 표시
INTERSECT
여러 개 SQL 문에 대한 교집합이다. 중복된 행은 하나로 표시한다. INTERSECT 연산을 이용한 SQL 문은 해당 연산자를 사용하지 않고도 동일한 결과집합을 출력하는 다양한 방법이 있어서 실무에서는 잘 사용하지 않음
EXCEPT(MINUS)
위 SQL 문의 집합에서 아래 SQL 문의 집합을 뺀 결과를 표시 MINU 연산 시 주의점은 MINUS를 하는 과정에서 중복된 행이 제거된다는 것임.

UNION과 UNION ALL의 결과집합

  • UNION 연산은 중복된 행에 대해 중복을 제거해서 출력하며 중복을 제거하는 과정에서 정렬을 수행하기도 함(DBMS 내부에서 작동). 하지만 SQL문 수행 시 집합의 정렬을 보장하기 위해서는 반드시 ORDER BY 절을 사용해야 함
  • UNION 및 UNION ALL 연산 시 ORDER BY 절에 기재하는 칼럼에는 앨리어스 사용할 수 없음
SELECT A.INDUTY_CL_CD , A.INDUTY_CL_NM FROM TB_INDUTY_CL A WHERE INDUTY_CL_SE_CD = 'ICS002' --중 AND A.INDUTY_CL_CD LIKE 'N%' --관광/여가/오락 UNION ALL SELECT B.INDUTY_CL_CD AS 업종분류코드, B.INDUTY_CL_NM AS 업종분류명 FROM TB_INDUTY_CL B WHERE B.INDUTY_CL_SE_CD = 'ICS002' --중 AND B.INDUTY_CL_CD LIKE 'O%' --숙박 ORDER BY INDUTY_CL_CD ;
  • UNION/UNION ALL 연산 시에 출력되는 집합의 헤더 값은 첫 번째 SQL문(맨 위의 SQL문)의 SELECT절에 기재한 칼럼명(혹은 앨리어스명)을 따르게 됨
 

계층형 질의와 셀프 조인

계층형 질의

  • 테이블에 계층형 데이터를 입력할 수 있고, 이러한 계층형 구조의 데이터를 SQL 문으로 표현하는 것을 계층형 질의 혹은 계층형 SQL 이라고 함
  • 또한 동일한 테이블끼리 조인 연산을 수행하는 조인 방식인 셀프 조인으로도 계층형 구조로 이루어진 데이터를 조회할 수 있음
SELECT A.INDUTY_CL_CD , A.INDUTY_CL_NM , B.INDUTY_CL_SE_CD , B.INDUTY_CL_SE_NM , LEVEL LVL , LPAD(' ', 4*(LEVEL-1))|| A.INDUTY_CL_CD || '(' || A.INDUTY_CL_NM || ')' AS "업종분류코드(명)" , CONNECT_BY_ISLEAF AS CBI FROM TB_INDUTY_CL A , TB_INDUTY_CL_SE B WHERE A.INDUTY_CL_SE_CD = B.INDUTY_CL_SE_CD START WITH A.UPPER_INDUTY_CL_CD IS null CONNECT BY PRIOR A.INDUTY_CL_CD = A.UPPER_INDUTY_CL_CD ORDER SIBLINGS BY A.INDUTY_CL_CD ;
  • START WITH 조건 : 계층 구조 전개의 시작 위치를 지정하는 구문. 즉 루트데이터를 지정함
  • CONNECT BY [NOCYCLE] [PRIOR] A AND B : CONNECT BY절은 다음에 전개될 자식 데이터를 지정하는 구문임
    • PRIOR PK(자식) = FK(부모) 형태를 사용하면 계층 구조에서 부모 데이터에서 자식 데이터(부모 → 자식) 방향으로 전개하는 순방향 전개를 한다.
    • PRIOR FK(부모) = PK(자식) 형태를 사용하면 반대로 자식 데이터에서 부모 데이터(자식 → 부모) 방향으로 전개하는 역방향 전개를 한다.
    • NOCYCLE을 추가하면 사이클이 발생한 이후의 데이터는 전개하지 않는다.
  • ORDER SIBLINGS BY 칼럼 : 형제 노드(동일 LEVEL)사이에서 정렬을 수행
  • CONNECT_BY_ROOT : 현재 행의 최상위 노드를 구함
  • SYS_CONNECT_BY_PATH : 계층형의 경로를 간편하게 출력하는 데 이용

계층형 SQL에서 제공하는 가상 칼럼

  • LEVEL : 루트 데이터면 1. 1부터 시작
  • CONNECT_BY_ISLEAF: 전개과정에서 해당 데이터가 리프 데이터면 1이고 아니면 0
  • CONNECT_BY_ISCYCLE : 전개과정에서 자식을 갖는데, 해당 데이터가 조상으로서 존재하면 1이고 그렇지 않으면 0이다.

SELF JOIN의 활용

SELECT A.INDUTY_CL_CD , NVL(A.INDUTY_CL_NM, '(Null)') AS INDUTY_CL_NM , NVL(A.UPPER_INDUTY_CL_CD, '(Null)') AS "상위업종분류코드" , NVL(B.UPPER_INDUTY_CL_CD, '(Null)') AS "차상위업종분류코드" FROM TB_INDUTY_CL A , TB_INDUTY_CL B WHERE A.UPPER_INDUTY_CL_CD = B.INDUTY_CL_CD AND A.INDUTY_CL_CD LIKE 'Q12%' --커피점/카페 ORDER BY A.INDUTY_CL_CD ;

서브 쿼리

서브쿼리란 하나의 SQL 문 안에 포함되어 있는 또다른 SQL 문을 말함. 조인은 조인에 참여하는 모든 테이블이 대등한 관계에 있기 때문에, 조인에 참여하는 모든 테이블의 칼럼을 어느 위치에서라도 자유롭게 참조할 수 있지만, 서브쿼리는다름
  • 서브 쿼리는 메인쿼리의 칼럼을 모두 사용할 수 있지만 메인 쿼리는 서브쿼리의 칼럼을 사용할 수 없음.

서브 쿼리 사용 시 주의점

  • 서브쿼리는 서브쿼리를 소괄호 “()”로 감싸서 사용
  • 서브쿼리는 단일행 또는 복수행 비교 연산자와 함께 사용 가능하다.
  • 단일행 비교 연산자는 서브 쿼리의 결과가 반드시 1건 이하여야 한다.
  • 복수행 비교 연산자는 서브쿼리의 결과 건수와 상관없다. 1건 혹은 여러 건도 가능하다.
  • 서브 쿼리 내에서는 ORDER BY 절을 사용하지 못한다. ORDER BY 절은 전체 SQL 문 내에서 오직 1개만 올 수 있기 때문에 ORDER BY 절은 메인쿼리의 맨 마지막 SQL문 아래에 위치해야 한다.

서브 쿼리 사용이 가능한 위치

  • SELECT절 : SELECT 절에 위치한 서브쿼리를 스칼라 서브쿼리라고 함
  • FROM 절 : FROM 절에 위치한 서브쿼리를 인라인뷰 서브쿼리라고 함
  • WHERE 절 : WHERE 절에 위치한 서브쿼리를 서브쿼리라고 함
  • HAVING 절 : HAVING 절에 위치한 서브쿼리를 서브쿼리라고 함
  • INSERT 문의 VALUES 절 : 서브쿼리라고 부름
  • UPDATE 문의 set 절 : 서브쿼리라고 부름

동작 방식에 따른 서브쿼리 분류

  • 비연관 서브쿼리 : 서브쿼리가 메인쿼리의 칼럼을 가지고 있지 않은 형태의 서브쿼리. 메인쿼리에 값을 제공하기 위한 목적으로 주로 사용
  • 연관 서브쿼리 : 서브쿼리가 메인쿼리의 값을 가지고 있는 형태의 서브쿼리. 일반적으로 메인쿼리가 먼저 수행되어 읽혀 진 데이터를 서브쿼리에서 조건이 맞는지 확인하고자 할 때 주로 사용함

반환 형태에 따른 서브쿼리 분류

단일행 서브쿼리
서브쿼리의 실행 결과가 항상 1건 이하인 서브쿼리를 의미함 항상 비교 연산자와 함께 사용됨 단일행 비교 연산자 =, <, <= , > .. 와 함께 사용됨
다중행 서브쿼리
서브쿼리의 실행 결과가 여러 건인 서브쿼리를 의미함 다중행 서브쿼리는 다중행 비교 연산자와 함께 사용됨 다중행 비교 연산자 IN, ANY, ALL, SOME, EXISTS 와 함께 사용됨
다중칼럼 서브쿼리
서브쿼리의 실행 결과로 여러(다중) 칼럼을 반환함 메인쿼리의 조건 절에 여러 칼럼을 동시에 비교할 수 있다. 서브쿼리와 메인쿼리의 칼럼 수와 칼럼 순서가 동일해야 한다.
SELECT A.TK_GFF_CNT , A.SUBWAY_STATN_NO , B.LN_NM , B.STATN_NM FROM TB_SUBWAY_STATN_TK_GFF A , TB_SUBWAY_STATN B WHERE A.STD_YM = '202010' --2020년 10월 AND A.BEGIN_TIME = '0800' --출근시간대 AND A.END_TIME = '0900' --출근시간대 AND A.SUBWAY_STATN_NO = B.SUBWAY_STATN_NO AND TK_GFF_SE_CD = 'TGS002' --하차 AND TK_GFF_CNT > ( SELECT K.TK_GFF_CNT FROM TB_SUBWAY_STATN_TK_GFF K WHERE K.SUBWAY_STATN_NO = '000615' --9호선 여의도역 AND K.STD_YM = '202010' --2020년 10월 AND K.BEGIN_TIME = '0800' --출근시간대 AND K.END_TIME = '0900' --출근시간대 AND K.TK_GFF_SE_CD = 'TGS002' --하차 ) ORDER BY A.TK_GFF_CNT desc ;
단일행 서브쿼리 사용
SELECT B.SUBWAY_STATN_NO , B.LN_NM , B.STATN_NM FROM TB_SUBWAY_STATN B WHERE B.SUBWAY_STATN_NO IN ( SELECT K.SUBWAY_STATN_NO FROM TB_SUBWAY_STATN_TK_GFF K WHERE K.STD_YM = '202010' --2020년 10월 AND K.BEGIN_TIME = '0800' --출근시간대 AND K.END_TIME = '0900' --출근시간대 AND K.TK_GFF_SE_CD = 'TGS002' --하차 AND K.TK_GFF_CNT >= 250000 ) ORDER BY B.SUBWAY_STATN_NO ;
다중행 서브쿼리 사용
 
SELECT A.ADSTRD_CD , B.ADSTRD_NM , A.STD_YM , A.POPLTN_SE_CD , A.AGRDE_SE_CD , A.POPLTN_CNT FROM TB_POPLTN A , TB_ADSTRD B WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD = 'T' AND (A.AGRDE_SE_CD, A.POPLTN_CNT) IN ( SELECT K.AGRDE_SE_CD , MAX(K.POPLTN_CNT) AS POPLTN_CNT FROM TB_POPLTN K WHERE K.STD_YM = '202010' --2020년 10월 기준 AND K.POPLTN_SE_CD = 'T' --인구구분코드 : 전체 GROUP BY K.AGRDE_SE_CD ) AND A.ADSTRD_CD = B.ADSTRD_CD ORDER BY A.AGRDE_SE_CD ;
다중 칼럼 서브쿼리 사용

EXISTS 문 서브쿼리 사용

SELECT A.SUBWAY_STATN_NO , A.LN_NM , A.STATN_NM FROM TB_SUBWAY_STATN A WHERE EXISTS ( SELECT 1 FROM TB_SUBWAY_STATN_TK_GFF K WHERE K.SUBWAY_STATN_NO = A.SUBWAY_STATN_NO AND K.STD_YM = '202010' AND TK_GFF_CNT >= 250000 ) ORDER BY A.SUBWAY_STATN_NO ;
  • EXISTS 문은 서브쿼리의 결과가 참이라면 결과집합에 포함시킴
  • SELECT 1 인 이유는 해당 조건에 해당 하는 값이 있는지 체크만 하면 되기에 칼럼 값 프린트가 아닌 그냥 1을 출력시킨것

인라인뷰 서브쿼리

SELECT B.SUBWAY_STATN_NO , B.LN_NM , B.STATN_NM , A.STD_YM , A.BEGIN_TIME , A.END_TIME , A.TK_GFF_SE_CD , A.TK_GFF_CNT FROM ( SELECT A.SUBWAY_STATN_NO , A.STD_YM , A.BEGIN_TIME , A.END_TIME , A.TK_GFF_SE_CD , A.TK_GFF_CNT FROM TB_SUBWAY_STATN_TK_GFF A WHERE A.STD_YM = '202010' AND A.BEGIN_TIME = '1800' AND A.END_TIME = '1900' AND A.TK_GFF_SE_CD = 'TGS002' AND A.TK_GFF_CNT > 150000 ) A , TB_SUBWAY_STATN B WHERE A.SUBWAY_STATN_NO = B.SUBWAY_STATN_NO ORDER BY A.TK_GFF_CNT DESC ;

HAVING 절의 서브쿼리 사용

SELECT A.SUBWAY_STATN_NO , (SELECT L.STATN_NM || '(' || L.LN_NM ||')' FROM TB_SUBWAY_STATN L WHERE L.SUBWAY_STATN_NO = A.SUBWAY_STATN_NO ) AS STATN_INFO , ROUND(MAX(A.TK_GFF_CNT), 2) AS TK_GFF_CNT FROM TB_SUBWAY_STATN_TK_GFF A WHERE A.STD_YM = '202010' AND A.BEGIN_TIME = '1800' AND A.END_TIME = '1900' AND A.TK_GFF_SE_CD = 'TGS002' GROUP BY A.SUBWAY_STATN_NO HAVING ROUND(MAX(A.TK_GFF_CNT), 2) > ( SELECT ROUND(AVG(A.TK_GFF_CNT), 2) AS AVG_TK_GFF_CNT FROM TB_SUBWAY_STATN_TK_GFF A WHERE A.STD_YM = '202010' AND A.BEGIN_TIME = '1800' AND A.END_TIME = '1900' AND A.TK_GFF_SE_CD = 'TGS002' ) ORDER BY TK_GFF_CNT DESC ;

UPDATE 문의 SET 절에 위치하는 서브쿼리

UPDATE TB_POPLTN A SET A.ADSTRD_NM = ( SELECT K.ADSTRD_NM FROM TB_ADSTRD K WHERE K.ADSTRD_CD = A.ADSTRD_CD );

INSERT 문에 사용되는 서브쿼리

INSERT INTO TB_SUBWAY_STATN_TK_GFF_SUM VALUES ('000615', (SELECT SUM(TK_GFF_CNT) FROM TB_SUBWAY_STATN_TK_GFF WHERE SUBWAY_STATN_NO = '000615' --9호선 여의도역 ) ) ;

뷰 사용하기

  • 뷰는 SQL문(SELECT문)을 뷰로 생성해 놓고, 해당 뷰만 호출하면 뷰 내부에 있는 SQL문(SELECT문)을 호출할 수 있는 역할을 함
  • 뷰를 사용함으로써 특정 업무에서 어떤 데이터를 조회할 때는 특정 뷰를 사용하는 것으로 지정할 수 있음
뷰 사용시 장점
  • 독립성 : 테이블 구조가 변경되어도 뷰를 사용하는 응용 프로그램은 변경하지 않아도 된다.
  • 편리성 : 복잡한 질의를 뷰로 생성 함으로써 관련 질의를 단순하게 작성할 수 잇다.
  • 보안성 : 개인정보와 같은 숨기고 싶은 민감한 정보가 존재한다면, 뷰를 생성할 때 해당 정보(칼럼)을 제외시키고 생성함으로써 사용자들에게 정보 노출을 하지 않을 수 있다.
CREATE OR REPLACE VIEW V_STARBUCKS_POPLTN_INFO AS SELECT A.BSSH_NO , A.CMPNM_NM , A.BHF_NM , A.ADSTRD_CD , B.ADSTRD_NM , SUM(C.POPLTN_CNT) AS SUM_POPLTN_CNT FROM TB_BSSH A , TB_ADSTRD B , TB_POPLTN C WHERE ( CMPNM_NM LIKE '%스타벅스%' OR UPPER(CMPNM_NM) LIKE '%STARBUCKS%' ) AND A.ADSTRD_CD = B.ADSTRD_CD AND B.ADSTRD_CD = C.ADSTRD_CD AND C.STD_YM = '202010' AND C.POPLTN_SE_CD = 'T' GROUP BY A.BSSH_NO, A.CMPNM_NM, A.BHF_NM, A.ADSTRD_CD, B.ADSTRD_NM ORDER BY A.BSSH_NO, A.CMPNM_NM, A.BHF_NM, A.ADSTRD_CD, B.ADSTRD_NM; SELECT A.BSSH_NO , A.CMPNM_NM , A.BHF_NM , A.ADSTRD_CD , A.ADSTRD_NM , A.SUM_POPLTN_CNT FROM V_STARBUCKS_POPLTN_INFO A ;
뷰 생성과 조회

그룹 함수

그룹함수의 종류

  • ROLLUP : 소그룹 간의 소계를 계산하는 기능
  • CUBE : 다차원적인 소계를 계산하는 기능. 결합 가능한 모든 값에 대하여 다차원 집계를 생성함
  • GROUPING SETS: 특정 항목에 대한 소계를 계산하는 기능

ROLLUP 함수를 이용한 합계 데이터 출력

SELECT A.AGRDE_SE_CD , SUM(A.POPLTN_CNT) AS POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD = 'T' GROUP BY ROLLUP(A.AGRDE_SE_CD) ORDER BY A.AGRDE_SE_CD ; 000 4005030 010 4818481 020 6802784 030 6900752 040 8312221 050 8655292 060 6669780 070 3687451 080 1714191 090 250335 100 21699 51838016 -- 합계 데이터
SELECT A.AGRDE_SE_CD , A.POPLTN_SE_CD , SUM(A.POPLTN_CNT) AS POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY ROLLUP(A.AGRDE_SE_CD, A.POPLTN_SE_CD) ORDER BY A.AGRDE_SE_CD ; --- 000 F 1951273 000 M 2053757 000 4005030 010 F 2325821 010 M 2492660 010 4818481
  • 위와 같이 쿼리하면 연령대별 인구수 합계, 연령대별 + 인구구분별 인구수 합계, 전체인구수 합계 가 출력됨

ROLLUP + GROUPING 함수를 이용한 합계 데이터 출력

  • ROLLUP 함수에 기재한 칼럼을 GROUPING 함수에 인자로 넣으면 합계를 표현하는 행에 대해서는 1이 출력됨. 이를 이용하여 CASE WHEN 문으로 합계/소계인 행에 대해 해당 합계가 어떤 합계인지 표현할 수 있음
SELECT CASE WHEN GROUPING(A.AGRDE_SE_CD) = 0 THEN A.AGRDE_SE_CD ELSE '전체합계' END AS AGRDE_SE_CD , CASE WHEN GROUPING(A.POPLTN_SE_CD) = 0 THEN A.POPLTN_SE_CD ELSE '연령대별남녀합계' END AS POPLTN_SE_CD , SUM(A.POPLTN_CNT) AS POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY ROLLUP(A.AGRDE_SE_CD, A.POPLTN_SE_CD) ORDER BY A.AGRDE_SE_CD;

CUBE 함수를 이용한 합계 데이터 출력

CUBE 함수는 인자로 기재한 칼럼에 대한 다차원 합계를 계산하는 데 사용됨
SELECT CASE WHEN GROUPING_AGRDE_SE_CD = 1 AND GROUPING_POPLTN_SE_CD = 1 THEN '전체합계' WHEN GROUPING_AGRDE_SE_CD = 1 AND GROUPING_POPLTN_SE_CD = 0 THEN '연령대별합계' WHEN GROUPING_AGRDE_SE_CD = 0 AND GROUPING_POPLTN_SE_CD = 1 THEN '성별합계' WHEN GROUPING_AGRDE_SE_CD = 0 AND GROUPING_POPLTN_SE_CD = 0 THEN '연령대+성별합계' ELSE '' END AS 합계구분 , NVL(AGRDE_SE_CD, '연령대합계') AS AGRDE_SE_CD , NVL(POPLTN_SE_CD, '성별합계') AS POPLTN_SE_CD , POPLTN_CNT FROM ( SELECT A.AGRDE_SE_CD , GROUPING(A.AGRDE_SE_CD) AS GROUPING_AGRDE_SE_CD , A.POPLTN_SE_CD , GROUPING(A.POPLTN_SE_CD) AS GROUPING_POPLTN_SE_CD , SUM(A.POPLTN_CNT) AS POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY CUBE(A.AGRDE_SE_CD, A.POPLTN_SE_CD) ORDER BY A.AGRDE_SE_CD ) A ;
  • CUBE 함수를 이용하면 “연령대구분별(AGRDE_SE_CD)”, “연령대구분별(AGRDE_SE_CD) + 인구구분별(POPLTN_SE_CD)”, “인구구분별(POPLTN_SE_CD)”, “전체”의 총 4개 기준의 합계를 구함

UNION ALL + GROP BY 를 이용한 합계 데이터 출력

SELECT A.AGRDE_SE_CD AS AGRDE_SE_CD , '성별전체' AS POPLTN_SE_CD , SUM(POPLTN_CNT) POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY AGRDE_SE_CD UNION ALL SELECT '연령대별전체' AS AGRDE_SE_CD , A.POPLTN_SE_CD AS POPLTN_SE_CD , SUM(POPLTN_CNT) POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY POPLTN_SE_CD UNION ALL SELECT '연령대별전체' AS AGRDE_SE_CD , '성별전체' AS POPLTN_SE_CD , SUM(POPLTN_CNT) POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') ORDER BY AGRDE_SE_CD, POPLTN_SE_CD, POPLTN_CNT ;
  • 위 SQL 문은 연령대구분코드별, 인구구분코드별, 전체 기준으로 인구수 합계를 구한 후 UNION ALL로 합친 모습임
  • 위의 SQL에서 나오는 결과를 GROUPING SETS를 이용하면 한번에 가능함
SELECT NVL(AGRDE_SE_CD, '연령대별전체') AS AGRDE_SE_CD , NVL(POPLTN_SE_CD, '성별전체') AS POPLTN_SE_CD , SUM(POPLTN_CNT) POPLTN_CNT FROM TB_POPLTN A WHERE A.STD_YM = '202010' AND A.POPLTN_SE_CD IN ('M', 'F') GROUP BY GROUPING SETS(AGRDE_SE_CD, POPLTN_SE_CD, ()) -- ()는 전체합계를 의미 ORDER BY AGRDE_SE_CD, POPLTN_SE_CD, POPLTN_CNT ;
합계 데이터 출력 — GROUPING SETS 사용
  • GROUPING SETS는 함수 인자의 순서가 서로 바뀌어도 동일한 결과집합을 출력함

DCL(Data Control Language)

특정 사용자의 권한을 제어할 수 있는 명령어. 데이터베이스에 존재하는 데이터의 보호와 보안을 위해서 유저의 권한을 관리해야 함.
  • DDL 문의 일종으로서 커밋 혹은 롤백이 필요없이 실행하는 순간 적용됨. 권한을 줄 때는 GRANT, 권한 회수할 때는 REVOKE 문을 사용
CREATE USER DCL_TEST IDENTIFIED BY 1234; -- DCL_TEST 유저를 만드는 DCL GRANT CREATE SESSION TO DCL_TEST; -- 접속 권한 부여 GRANT CREATE TABLE TO DCL_TEST; -- 테이블 생성 권한 부여 GRANT SELECT ON SQLD.TB_ADRES_CL_SE TO DCL_TEST; -- 테이블 조회 권한 부여 GRANT INSERT, DELETE, UPDATE ON SQLD.TB_ADRES_CL_SE TO DCL_TEST; -- DCL_TEST 계정 -- 에게 SQLD 계정이 소유한 테이블의 DML 권한 주기 -- 테이블 DML 권한 회수 REVOKE SELECT ON SQLD.TB_ADRES_CL_SE FROM DCL_TEST; REVOKE INSERT, DELETE, UPDATE ON SQLD.TB_ADRES_CL_SE TO DCL_TEST; REVOKE CREATE TABLE FROM DCL_TEST;

ROLE을 이용한 권한 부여

CREATE ROLE CREATE_SESSION_TABLE; -- ROLE 생성 GRANT CREATE SESSION, CREATE TABLE TO CREATE_SESSION_TABLE; -- ROLE에 권한 추가 GRANT CREATE_SESSION_TABLE TO DCL_TEST; -- 사용자에게 ROLE 권한 부여

오라클 DBMS에서 일반적으로 부여하는 ROLE

대표적인 ROLE
  • CONNECT : 데이터베이스에 접속할 수 있는 CREATE SESION 권한 존재
    • CREATE SESSION
  • RESOURCE : 각종 데이터베이스의 객체를 생성할 수 있는 권한이 주어짐
    • CREATE CLUSTER
    • CREATE PROCEDURE
    • CREATE TYPE
    • CREATE SEQUENCE
    • CREATE TRIGGER
    • CREATE OPERATOR
    • CREATE TABLE
    • CREATE INDEXTYPE

DCL_TEST 계정 제거 및 재생성, 기본 ROLE 부여

DROP USER DCL_TEST CASCADE; -- 유저가 가지고 있는 모든 오브젝트 및 유저를 제거하는 SQL 문 CREATE USER DCL_TEST IDENTIFIED BY 1234; GRANT CONNECT, RESOURCE TO DCL_TEST; -- 대표적인 Role 2개를 부여