표준 조인, 집합 연산자, DCL 계층형 질의, 그룹 함수, 서브쿼리, 윈도우 함수, 절차형 SQL, 집합 연산자에 대해 알아보자!
SELECT
-> WHERE
절PROJECT
-> SELECT
절(Natural)JOIN
->JOIN
연산DIVIDE
-> 현재 사용XSTANDARD JOIN
: ANSI JOIN
, 표준 조인
으로 불리며 모든 벤더별로 돌아가는 표준 JOIN 쿼리
INNDER JOIN
조건
에 충족하는 데이터만
출력ON
절에 조건
적어야 함select s.col1, t.col1, t.col2
from study s inner join test t
on s.col1=t.col1;
OUTER JOIN
조건
에 충족하는 데이터가 아니
어도 출력LEFT OUTER JOIN
-왼쪽
에 표기된 테이블의 데이터는 무조건 출력
되는 JOIN
-오른쪽
테이블에 데이터가 없는 행은 값이 NULL
로 출력
RIHGT OUTER JOIN
-오른쪽
에 표기된 테이블의 데이터는 무조건 출력
되는 JOIN
-왼쪽
테이블에 데이터가 없는 행은 값이 NULL
로 출력
FULL OUTER JOIN
-왼쪽, 오른쪽
테이블의 데이터가 모두 출력(중복값 제거 합집합)
NATURAL JOIN
A테이블
과 B테이블
에서 같은 이름
을 가진 컬럼들이 모두 동일한 데이터
를 가지고 있을 경우 JOINUSING
조건절을 이용해서 같은 이름을 가진 컬럼
중 원하는 컬럼
만 JOIN에 이용 가능USING절
로 정의된 컬럼 앞에는 SELECT절
에서 별도의 Alias
나 테이블명
X
ON
절 사용 불가공통 컬럼
앞에 OWNER 명
을 붙이면 에러 발생select * from test natural join study;
select * from test natural join study;
ex ) USING
SELECT CAST, GENDER, a.job as r_job, b.job as i_job
from run a join infinite b
using (CAST, GENDER);
CAST
와 GENDER
만 같은 이름에 같은 내용이면 natural join 된다!
CROSS JOIN(Cartesian Product)
A테이블
과 B테이블
사이에 JOIN 조건이 없는 경우
, 조합할 수 있는 모든 경우
출력카티션 곱
이라고 함속성
: 두 테이블의 속성 수 합
행
: 두 테이블의 행x행
select * from author cross join test;
UNION
연산->UNION
INTERSECTION
연산->INTERSECT
DIFFERENCE
연산->MINUS/EXCEPT
PRODUCT
연산->CROSS JOIN
합집합
중복된 행
도 그대로 출력
합집합
중복된 행
은 한 줄
로 출력union
사용하는 것이 union all
보다 성능상 불리교집합
중복된 행
은 한 줄
로 출력앞
에 있는 쿼리 결과 집합에서 뒤
에 있는 쿼리의 결과 집합을 뺀 차집합
중복된 행
은 한 줄
로 출력NOT EXISTS
또는 NOT IN
연산으로 구현 가능계층 구조
를 이루는 컬럼이 존재시 계층 쿼리
를 이용해 데이터 출력계층형 데이터
: 동일 테이블
에 계층적
으로 상위
와 하위
데이터가 포함된 데이터계층 쿼리
에서 정렬
을 위해선 형제들
끼리 정렬하는 ORDER SILBLINGS BY
절을 사용MSSQL
에서의 계층형 질의문
은 CTE(Common Table Expression)
을 재귀 호출
함으로써 계층 구조 전개MSSQL
에서 계층형 질의문은 앵커 멤버
를 실행하여 기본 결과 집합
을 만들고 이후 재귀 맴버를 지속적으로 실행
PRIOR
키워드는 SELECT, WHERE
절에서도 사용 가능Oracle
의 계층형 질의문에서 WHERE
절은 모든 전개
를 진행한 후의 필터 조건
connect by prior 자식=부모; --순방향 전개
connect by prior 부모=자식; --역방향 전개
select level,
sys_connect_by_path('['||cate_type||']'||cate_name,'-') as path
from cate
start with parent_cate is null
connect by prior cate_name=parent_cate;
LEVEL
: 현재의 depth
. 루트 노드는 1
SYS_CONNECT_BY_PATH(컬럼, 구분자)
: 루트
노드부터 현재
노드까지의 경로 출력START WITH
: 경로 시작 루트노드 생성. 계층 구조 전개 시작 위치 지정CONNECT BY
: 루트
로부터 자식 노드
를 생성해주는 절. 조건에 만족하는 데이터 없을 때 까지 노드 생성PRIOR
: 바로 앞
의 부모 노드 값
반환. 현재 읽은 칼럼 지정select level, cate_type, cate_name, parent_cate,
connect_by_root cate_name as root,
connect_by_isleaf as leaf
from cate
start with parent_cate is null
connect by prior cate_name=parent_cate;
CONNECT_BY_ROOT 컬럼
: 루트 노드
의 주어진 컬럼
값 반환CONNECT_BY_ISLEAF
: 가장 하위 노드인 경우
1
반환, 그 외에는 0
select level,
sys_connect_by_path('['||cate_type||']'||cate_name,'-') as path
from cate
start with cate_type='소'
connect by cate_name=prior parent_cate;
한 테이블 내
에 연관
이 있는 두 개의 컬럼
이 존재할 경우 수행같은 테이블
이 두번 이상 등장하므로 Alias
반드시 표기 필요ex) 쇼핑몰 상품의 카테고리가 대-중-소
select a.cate_type, a.cate_name, b.cate_type, b.cate_name
from cate a, cate b
where a.cate_name=b.parent_cate
and a.cate_type='대';
select a.cate_type, a.cate_name, b.cate_type, b.cate_name, c.cate_type, c.cate_name
from cate a, cate b, cate c
where a.cate_name=b.parent_cate
and b.cate_name=c.parent_cate;
서브쿼리(subquery)
: 하나의 쿼리 안
에 존재하는 또 다른 쿼리
밖의 쿼리
: 메인 쿼리
안에 있는 쿼리
: 서브 쿼리
메인 쿼리
의 컬럼
이 포함된 서브쿼리를 연관 서브쿼리
, 메인 쿼리의 컬럼이 포함되지 않은 서브쿼리를 비연관 서브쿼리
라고 함다중 행 서브쿼리
: IN
절과 함께 사용 (=
과 함께 사용 불가)SELECT절
: 스칼라 서브쿼리
FROM절
: 인라인 뷰
WHERE절, HAVING절
: 중첩 서브쿼리
괄호
로 감싸서 사용단일 행
또는 복수 행
비교 연산자와 함께 사용 가능단일 행 비교 연산자
는 서브쿼리의 결과가 반드시 1건 이하복수 행 비교 연산자
는 서브쿼리의 결과 건수와 상관 없다.서브쿼리
에서는 ORDER BY
를 사용하지 못한다.select
절에 오직 한 개
만 올 수 있기 때문에 메인쿼리의 맨 마지막 문장에 order by
위치.SELECT
절에 위치컬럼
이 올 수 있는 대부분 위치에 사용 (update 문의 set절, order by절
)컬럼 대신 사용
되므로 반드시 하나의 값만을 반환해야 함
(하나의 컬럼만)select m.product_id,
(select s.product_name
from product s
where s.product_id=m.product_id) as product_name,
m.member_id,
m.content
from product_review m;
--error
select m.product_id,
(select s.product_name, s.price
from product s
where s.product_id=m.product_id) as product_name,
m.member_id,
m.content
from product_review m;
--correct
select m.product_id,
(select s.product_name
from product s
where s.product_id=m.product_id) as product_name,
(select s.price
from product s
where s.product_id=m.product_id) as price,
m.member_id,
m.content
from product_review m;
FROM
절에 위치테이블명
이 올 수 있는 위치에 사용서브쿼리
의 결과가 마치 실행 시에 동적
으로 생성된 테이블인 것 처럼 사용 가능SQL 문
이 실행될 때만 임시적
으로 생성되는 동적인 뷰
이기 때문에, 해당 정보가 DB에 저장Xselect m.product_code,s.product_name, s.price,m.meber_id, m.content
from product_review m,
(select product_code, product_name, price from product) s
where m.product_code=s.product_code;
WHERE
절과 HAVING
절에 사용메인 쿼리와의 관계
비연관 서브쿼리(un-correlated subquery)
: 서브쿼리
내에 메인 쿼리
컬럼 존재 X
select name, job, birthday, agency_code
from ent
where agency_code = (select agency_code
from agency
where agency_name='dang');
2.연관 서브쿼리(Correlated subquery)
: 서브쿼리
내에 메인 쿼리
컬럼 존재
select order_no, drink_code, order_cnt
from cafe_order a
where order_cnt = (select max(order_cnt)
from cafe_order b
where b.drink_code=a.drink_code);
반환하는 데이터 형태
1. 단일 행 서브쿼리(Single Row)
: 서브쿼리가 항상 1건 이하
의 데이터 반환
단일행 비교 연산자(=,<,>,<=,>=,<>)
와 함께 사용select * from product
where price=(select max(price) from product);
2.다중 행 서브쿼리(Multi Row)
: 서브쿼리가 여러 건(2건 이상)
의 데이터 반환
다중행 비교 연산자(IN,ALL,ANY,SOME,EXISTS)
와 함께 사용select * from product
where product_code in (select product_code from product_review);
3.다중 컬럼 서브쿼리(Multi Column)
: 서브쿼리가 여러 컬럼
의 데이터 반환
MSSQL
에서 지원Xselect * from employees
where (job id,salary) in (select job_id, max_salary
from jobs
where max_salary=10000);
SELECT 문
에 이름
을 붙여서 재사용
이 가능하도록 저장해놓은 오브젝트
테이블
처럼 사용 가능가상테이블
실제
데이터 저장 X, 해당 데이터를 조회해오는 select문
만 가지고 있음실제 데이터
를 저장하고 있는 뷰를 생성하는 기능을 지원하는 DBMS
도 존재create or replace view 이름 as
select 컬럼들
from 테이블;
--ex
create or replace view dept_mem as
select a.depart_id,
a.depart_name,
b.first_name,
b.last_name
from depart a
left outer join employees b
on a.depart_id=b.depart_id;
drop view dept_mem;
보안성
: 보안
이 필요한 컬럼을 가진 테이블일 경우, 해당 컬럼을 제외
한 별도의 뷰를 생성하여 제공함으로써 보안 유지독립성
: 테이블 스키마가 변경
되었을 경우 어플리케이션은 변경하지 않고
관련 뷰만 수정. 테이블 구조
가 변경되어도 뷰
를 사용하는 응용 프로그램
은 변경하지 않아도 된다.편리성
: 복잡한 쿼리 구문
을 뷰 명
으로 단축시킴으로써 가독성
을 높이고 편리
하게 사용 가능. 복잡한 질의
를 뷰로 생성함으로써 관련 질의를 단순
하게 작성할 수 있으며, 해당 형태의 sql문을 자주 사용할 때 뷰
를 이용하면 편리하게 사용 가능투명성X
-- 내부적으로 뷰를 생성하는 sql을 볼 수 없기 때문그룹 함수
: 데이터를 GROUP BY
하여 나타낼 수 있는 데이터
를 구하는 함수집계 함수(count, sum, avg, max, min)
과 소계 함수(rollup, cube, grouping sets)
ROLLUP
함수는 인수의 순서
에 따라 결과 달라짐
CUBE/GROUPING SETS
함수는 인수의 순서가 바뀌어도 같은 결과
일반 그룹 함수
를 사용하여 CUBE, GROUPING SETS, ROLLUP
과 같은 결과 추출 가능집계된 컬럼 이외
의 대상 컬럼 값은 NULL값 반환select ~~
from ~~~
group by rollup(~~) --or group by cube(~~) etc..
소그룹 간 소계
및 총계
계산 함수ROLLUP(A,B)
: A, B로 그룹핑, A로 그룹핑, 총합계소그룹 간 소계
및 총계
를 다차원적
으로 계산rollup
이 일방향 소계
라면, cube
는 조합할 수 있는 모든 그룹에 대한 소계
집계CUBE(A,B,C)
: A,B,C로 그룹핑, A,B로 그룹핑, B,C로 그룹핑, A,C로 그룹핑, A로 그룹핑, B로 그룹핑, C로 그룹핑, 총합계시스템에 많은 부하 발생
다차원
집계를 생성order by
절에 명시적으로 정렬 칼럼 표시
특정 항목
에 대한 소계
계산인자값
으로 rollup
이나 cube
사용 가능grouping sets(a,b,())
: A로 그룹핑, B로 그룹핑, 총합계grouping sets(a,rollup(b,c))
: a로 그룹핑, b,c로 그룹핑, b로 그룹핑, 총합계
group by
와 union all
을 이용하여 동일한 결과 출력 가능동일 결과
ROLLUP, CUBE, GROUPING SETS
등과 함께 사용되며 소계
를 나타내는 ROW 구분
그룹핑 기준 칼럼 제외
모두 null
로 표현하였지만, 원하는 위치에 원하는 텍스트 출력 가능소계가 계산
된 ROW
에서는 GROUPING 함수 결과
값이 1
, 나머지는 0
select order_dt,
grouping(order_dt),
count(*)
from order
group by rollup(order_dt)
order by order_dt;
총합계
만 order_dt
가 null
로 출력되고 grouping
은 1로 출력된다.
나머지에서는 다 0으로 출력
select case grouping(order_dt)
when 1 then 'total' else order_dt
end as order_dt,
count(*)
from order
group by rollup(order_dt)
order by order_dt;
총 합계가 TOTAL
로 출력
select case grouping(order_dt)
when 1 then 'all dates' else order_dt
end as order_dt,
case grouping(order_item)
when 1 then 'all items' else order_item,
count(*)
from order
group by rollup(order_dt,order_item)
order by order_dt;
order_dt 그룹핑 시 order_item은 all items로 나오고,
전체 합계시에는 (all dates, all items)로 나온다.
ex ) 테이블에서 급여가 높은 2명을 내림차순으로 출력, 같은 급여를 받는 사원은 같이 출력
select top(2) with ties ename, sal
from emp
order by sal desc;
OVER
키워드와 함께 사용Partition
과 Group By
구문은 의미적으로 유사Partition
구문이 없으면 전체 집합
을 하나의 Partition으로 정의하는 것과 동일동일
Partition
을 넘을 수 없다.함수 | 종류 |
---|---|
순위 함수 | rank, dense_rank, row_number |
집계 함수 | sum,max,min,avg,count |
행 순서 함수 | first_value,last_value,lag,lead |
비율 함수 | cum_dist, percent_rank, ntile, ratio_to_report |
1.RANK()
같은 순위 존재시 존재하는 수 만큼 다음 순위 건너뜀
ORDER BY
를 포함한 QUERY
문에서 특정 칼럼에 대한 순위
를 구하는 함수.--날짜별 주문 건수 카운트해서 순위
select order_dt, count(*),
rank() over(order by count(*) desc) as rank
from order
group by order_dt;
--출력
1
2
3
4
5
6
7
7
7
10
--부서별로 급여가 높은 사원부터 순위
select first_name, last_name, depart_id, salary,
rank() over(partition by depart_id order by salary desc) as rank
from employees;
2.DENSE_RANK()
같은 순위가 존재
하더라도 다음 순위를 건너뛰지 않고
이어서 매긴다--날짜별 주문 건수 카운트해서 순위
select order_dt, count(*),
dense_rank() over(order by count(*) desc) as dense_rank
from order
group by order_dt;
--출력
1
2
3
4
5
6
7
7
7
8
3.ROW_NUMBER()
동일한 값
이라도 각기 다른 순위 부여
1.SUM()
합계
구하는 함수range
옵션은 동일한 데이터
가 있을 경우 모두 합한 값
출력-- 데이터의 누적값 구함
select stu_name, subject, score,
sum(score) over (partition by stu_name
order by subject desc
range unbounded preceding) as total
from sqld;
--order by절에 sum컬럼 명시시 누적합 집계
--하지만, 전체 학생들의 점수 누적 합
select stu_name, subject, score,
sum(score) over (order by score desc) as total
from sqld;
2.MAX()
최댓값
구하는 함수--과목별 최대 점수 받은 사람
select stu_name,subject, score
from (select stu_name, subject,score,
max(score) over(partition by subject) as max_score
from sqld)
where score=max_score;
3.MIN()
최솟값
구하는 함수
4.AVG()
평균값
구하는 함수
5.COUNT()
건수
구하는 함수select stu_name, subject, score,
count(*)over (partition by subject) as pass
from sqld
where result='pass';
--과목별 본인보다 점수가 높거나 "같은" 건수 카운트
select stu_name, subject, score,
count(*)over (partition by subject
order by score desc
range unbounded preceding) as high
from sqld;
--출력
1
2
3
4
5
1
2
3
5 --밑과 동일값
5 --본인도 카운트 하기 때문
order by
뒤에는 꼭 범위를 명시해주자!1.FIRST_VALUE()
가장 선두
에 위치한 데이터를 구하는 함수MSSQL
에서 지원 Xselect stu_name, subject, score,
first_value(score) over(order by score) as first
from sqld;
제일 첫 행의 score
인 7
이 모든 행의 first열
에 기록
2.LAST_VALUE()
가장 끝
에 위치한 데이터를 구하는 함수MSSSQL
에서 지원 Xselect stu_name, subject, score,
last_value(score) over(order by score) as last
from sqld;
--출력은 각자의 score로 됨
각 row의 score
과 동일한 값이 출력된다.
windowing 절
의 default
가 RANGE UNBOUNDED PRECEDING
이기 때문이다.
=> 파티션 범위 : 맨 위 끝 행~현재 행까지
select stu_name, subject, score,
last_value(score) over(order by score
range between unbounded preceding
and unbounded following) as last
from sqld;
3.LAG()
특정 수
만큼 앞선
데이터를 구하는 함수MSSQL
에서 지원XLAG(score,3)
: 3칸 앞선 행의 값default
는 1
4.LEAD()
특정 수
만큼 뒤에 있는
데이터를 구하는 함수MSSQL
에서 지원XLEAD(score,3)
: 3칸 뒤의 행 값LEAD(sal,3,-1)
: 만약 null일 경우 세번 째 인자인 -1
이 나옴1.RATIO_TO_REPORT
합계
에서 차지하는 비율
을 구하는 함수MSSQL
에서 지원Xsum(행)
2.PERCENT_RANK
맨 위
행을 0
, 맨 아래
행을 1
로 놓고, 현재 행이 위치하는 백분위 순위 값
을 구하는 함수MSSQL
에서 지원X
3.CUME_DIST
누적 백분율
을 구하는 함수0
보다 크고
1
보다 작거나 같은 값
MSSQL
에서 지원X
4.NTILE
n등분
한 후 현재 행에 해당하는 등급 구하는 함수select stu_name, subject,score,
ntile(3) over (order by score desc) as ntile
from sqld;
-- 행이 총 10개라면
1
1
1
1
2
2
2
3
3
3
할당 행 남을 경우 맨 앞의 그룹부터 하나씩 채워짐
범위 | 뜻 |
---|---|
unbounded preceding | 위쪽 끝 행 |
unbounded following | 아래쪽 끝 행 |
current row | 현재 행 |
n preceding | 현재 행에서 위로 n만큼 이동 |
n following | 현재 행에서 아래로 n만큼 이동 |
기준 | 뜻 |
---|---|
ROWS | 행 자체가 기준 |
range | 행이 가지고 있는 데이터 값이 기준 |
ex)
--처음부터 현재 행 까지. ==range unbounded preceding과 같은 의미
range between unbounded preceding and current row;
--현재 행이 가지고 있는 값보다 10만큼 적은 행 부터 현재 행 까지
--==range 10 preceding과 같은 의미
range between 10 preceding and current row;
--현재 행 부터 끝까지
rows between current row and unbounded following;
--현재 행부터 아래로 5만큼 이동한 행 까지
rows between current row and 5 following;
ROWNUM
은 슈도 컬럼위의 행에서 +1
이 되기 때문에 where rownum=2
처럼 건너뛰기 안됨<
조건 또는 <=
조건으로 사용select rownum, 이름, 국어, 영어, 수학
from (select 이름, 국어, 영어, 수학
from exam_score
order by 국어 desc, 영어 desc, 수학 desc)
where rownum<=5;
-- 점수 상위 5개 뽑아내는 것 !! 꼭 인라인 뷰로 사용하자
--아래는 안됨
select rownum, 이름, 국어, 영어, 수학
from exam_score
where rownum<=5
order by 국어 desc, 영어 desc, 수학desc
--where 절보다 order by는 늦게 실행되기 때문.
DCL(Data Control Language)
: 데이터베이스에 접근
하고 객체들을 사용
하도록 권한을 주고 회수
하는 명령어
USER
를 생성하고 권한
을 부여하거나 회수하는 명령어WITH GRANT OPTION
CASCADE
하나의 DB는 여러 개의 USER
를 가질 수 있다.
1.CREATE USER
생성
명령어CREATE USER
권한이 있어야 수행 가능create user 사용자명 identified by 패스워드;
2.ALTER USER
변경
명령어--패스워드 변경
alter user 사용자명 identified by 패스워드;
3.DROP USER
삭제
명령어drop user 사용자명 [cascade];
cascade
옵션 사용 시 사용자명
이 생성한 모든 object 함께 삭제
1.GRANT
권한 부여
grant 권한 to 사용자명;
2.REVOKE
권한 회수
revoke 권한 from 사용자명;
ROLE
: 특정 권한들을 하나의 세트
처럼 묶는 것
ROLE
생성
create role 롤명;
2.role
에 권한 부여
grant 권한 to 롤명;
--ex
grant create table, create user to create_roll;
3.role
을 사용자에게 부여
grant 롤명 to 사용자명;
Block구조
로 되어있어 각 기능별로 모듈화
가능SQL 문장 간
값
을 교환IF, LOOP
등 절차형 언어를 사용하여 절차적인 프로그래밍
이 가능하도록 함DBMS 에러
나 사용자 정의 에러
를 정의하여 사용 가능PL/SQL
은 Oracle
에 내장되어 있으므로 Oracle
과 PL/SQL
을 지원하는 어떤 서버로도 프로그램 옮기
기 가능성능 향상
여러 SQL
문장을 Block
묶고 한 번
에 block 전부를 서버
로 보내버리기 때문에 통신량 줄일 수 있다
일반 sql 문장
을 실행할 때 where절의 조건
등으로 대입 가능Procedure
내부에 작성된 절차적 코드
는 PL/SQL엔진
이 처리하고, 일반적인 sql 문장
은 sql 실행기
가 처리다른 프로시저 호출
시 호출 프로시저의 트랜잭션
과는 별도
로 PRAGMA AUTONOMOUS_TRANSACTION
선언 시 자율 트랜잭션 처리 가능 => 작성자 기준 트랜잭션 분할 가능
동적 SQL
또는 DDL
문장 실행 시 EXECUTE IMMEDIATE
를 사용해야 함SQL
을 로직
과 함께 DB내에 저장해놓은 명령문의 집합
사용자 정의 함수
는 단독적으로 실행되기 보다는 다른 SQL문을 통하여 호출
되고 그 결과를 리턴
하는 SQL의 보조적인 역할
SQL 문장
을 DB서버에 저장하여 사용자
와 애플리케이션
사이에 공유
할 수 있도록 만든 일종의 SQL 컴포넌트 프로그램
독립적
으로 실행되거나 다른 프로그램으로부터 실행
될 수 있는 완전한 실행 프로그램
프로시저(Procedure)
사용자 지정 함수(User Defined Function)
트리거(Trigger)
DML문
이 수행되었을 때, 데이터베이스
에서 자동
으로 동작
하도록 작성된 저장 프로그램트리거
는 데이터 무결성, 일관성
을 위해서 사용트리거
는 트랜잭션 제어 불가
, TCL 불가
트리거
는 DB에 로그인 하는 작업
에도 정의 가능프로시저 | 트리거 |
---|---|
CREATE Procedure 문법 사용 | CREATE Trigger 문법 사용 |
EXECUTE 명렁어로 실행 | 생성 후 자동 실행 |
COMMIT, ROLLBACK 실행 가능 | COMMIT, ROLLBACK 실행 안됨 |
커서 생성
CURSOR 커서이름 IS 커서정의;--커서 생성
OPEN 커서이름; --커서 사용 시작
FETCH 커서이름 INTO 변수; --커서에서 행 데이터를 가져옴. 커서에서 원하는 결과 추출
CLOSE 커서이름; --커서 종료