계정 + 테이블 + 스키마
데이터의 정확성과 일관성을 유지하고 결손과 부정합이 없음을 보장
기본키 => NULL, 중복이 아니다
외래키 => NULL 허용, 기본키 값
정해진 도메인에 속한다
NULL을 허용하지 않는다
중복을 허용하지 않는다
1관계 당 1키
CREATE, ALTER, DROP, TRUNCATE
INSERT, DELETE, UPDATE, MERGE
GRANT, REVOKE
COMMIT, ROLLBACK
SELECT
SELECT * | 컬럼명 | 표현식
FROM 테이블명 or 뷰명
WHERE 조회 조건
GROUP BY 그룹핑컬럼명
HAVING 그룹핑 필터링 조건
ORDER BY 정렬컬럼명
문자열을 소문자로 변경
문자열을 대문자로 변경
문자열의 m위치에서 n개의 문자열 추출
문자열에서 찾을문자열 위치 반환
m 위치에서 시작하여 n번째 발견된 문자열 위치
문자열 중 삭제문자열을 왼쪽에서 삭제
문자열 중 삭제문자열을 오른쪽에서 삭제
문자열 중 특정 문자열을 양옆에서 삭제
문자열 왼쪽에 추가문자열을 추가하여 총 n의 길이를 반환
문자열 오른쪽에 추가문자열을 추가하여 총 n의 길이를 반환
문자열1 + 문자열2
문자열 길이 반환
문자열에서 찾을문자열을 바꿀문자열로 치환
글자를 1대 1로 치환
절대값 반환
자리수 이전에서 반올림
자리수 이전에서 버림
숫자가 양수면 1, 음수면 -1, 0이면 0 반환
작거나 같은 최대 정수 반환
크거나 같은 최소 정수 반환
숫자1 나누기 숫자2, 하여 나머지 반환
m의 n 제곱
루트값
대상이 값1이면 리턴1, 값2 이면 리턴 2 .... 그외 그외리턴
대상이 NULL이면 치환값 반환 아니라면 대상 반환
대상이 NULL이면 치환값2, 아니라면 치환값1 반환
대상들 중 NULL이 아닌 값 출력
모두 NULL이면 그외 출력
대상이 NULL이면 치환값 반환
대상1 == 대상2 이면 NULL 반환
다르면 대상1 반환
SELECT VAL1,
CASE VAL1 WHEN 5 THEN '값1'
WHEN 10 TEHN '값2'
ELSE '기타'
END AS VAL2
S% // S로 시작하는 문자열
%S // S로 끝나는 문자열
%S% // 중간에 S가 들어가는 문자열
_S% // _(1자리), S가 두번째인 문자열
SELECT dept, name, AVG(salary)
FROM emp
GROUP BY dept;
=> 오류 발생, name이 GROUP BY에 없고 집계함수도 아니기 때문에, dept 그룹에 직원이 여러명인데 어느 name을 출력할 지 결정할 수 없다.
여러 테이블의 데이터를 사용하여 동시 출력하거나 참조할 경우 사용
조건이 성립하는 행만 반환
SELECT 학생.이름, 수강.강의코드
FROM 학생
INNER JOIN 수강 ON 학생.학번 = 수강.학번;
=> 학번을 기준으로 조인하며, 수강 내역이 없는 학생은 제외
한쪽 테이블에는 데이터가 있지만, 다른 테이블에는 없는 경우에도 결과를 반환
왼쪽 테이블의 모든 행을 반환하고, 오른쪽 테이블에 일치하는 데이터가 없을 경우 NULL을 반환
오른쪽 테이블의 모든 행을 반환하고, 왼쪽 테이블에 일치하는 데이터가 없을 경우 NULL을 반환
왼쪽과 오른쪽 테이블의 모든 데이터를 반환
NULL로 채워진다모든 경우의 행의 조합
같은 테이블을 2번 이상 참조하여 연결
SELECT A.이름 AS 직원, B.이름 AS 관리자
FROM 직원 A
LEFT JOIN 직원 B ON A.관리자ID = B.직원ID;
두 테이블 간 칼럼값이 서로 정확히 일치하는 경우 사용
SELECT 테이블1.칼럼명, 테이블2.칼럼명, ...
FROM 테이블1, 테이블2
WHERE 테이블1.칼럼명1 = 테이블2.칼럼명2;
두 테이블 간 칼럼값이 서로 정확하게 일치하지 않는 경우 사용
SELECT 테이블1.칼럼명, 테이블2.칼럼명
FROM 테이블1, 테이블2
WHERE 테이블1.칼럼명1 BETWEEN 테이블2.칼럼명1 AND 테이블2.칼럼명2;
AVG(COL1) -> NULL, 30, 50 이면 80/2 로 계산한다.
SUM(COL1+COL2+COL3) -> 행별로 계산한다.
공집합의 집계함수 결과도 위와 동일하다.쿼리 안의 쿼리
메인 쿼리의 각 행을 참조하면서 실행되는 서브쿼리
EXISTS 연산자 사용SELECT 이름
FROM 학생 S
WHERE EXISTS (
SELECT 1
FROM 수강 C
WHERE C.학번 = S.학번 AND C.강의코드 = 'CS101'
);
학생 테이블의 각 행을 참조 -> 수강 테이블에서 학번이 CS101 강의를 수강했는지 확인 -> 존재할 경우 해당 학생의 이름을 반환
메인 쿼리 내 컬럼이 존재하지 않는 서브쿼리
SELECT 이름, 점수
FROM 학생
WHERE 점수 > (SELECT AVG(점수) FROM 학생);
서브쿼리가 먼저 실행되어 평균 점수를 계산 -> 해당 평균 점수보다 높은 학생만을 메인쿼리가 조회
서브쿼리 결과와 값이 같은 모든 행 출력
WHERE COL1 IN (SELECT ~)
서브쿼리 결과 중, 최댓값보다 큰 값을 갖는 모든 행 출력
WHERE COL1 > ALL (SELECT ~)
서브쿼리 결과 중, 최솟값보다 작은 값을 갖는 모든 행 출력
WHERE COL1 < ALL (SELECT ~)
서브쿼리 결과 중, 최솟값보다 큰 값을 갖는 모든 행 출력
WHERE COL1 > ANY (SELECT ~)
서브쿼리 결과 중, 최댓값보다 작은 값을 갖는 모든 행 출력
WHERE COL1 < ANY (SELECT ~)
데이터의 특정 범위(윈도우) 내에서 계산
데이터를 특정 기준으로 정렬
SELECT 이름, 점수,
RANK() OVER (ORDER BY 점수 DESC) AS 순위
FROM 학생;
SELECT 이름, 점수,
DENSE_RANK() OVER (ORDER BY 점수 DESC) AS 순위
FROM 학생;
SELECT 이름, 점수,
ROW_NUMBER() OVER (ORDER BY 점수 DESC) AS 행번호
FROM 학생;
현재 행을 기준으로 윈도우 프레임 설정
SELECT 이름, 점수,
SUM(점수) OVER (ORDER BY 점수 DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 누적점수
FROM 학생;
=> 현재 행까지의 점수 누적 합산
물리적인 행 개수 기준으로 인도우 설정
ORDER BY 기준값이 동일한 행 포함(논리적 범위)
| 키워드 | 설명 |
|---|---|
UNBOUNDED PRECEDING | 해당 파티션의 첫 번째 행부터 현재 행까지 |
n PRECEDING | 현재 행을 포함하여 이전 n개 행까지 |
CURRENT ROW | 현재 행만 포함 |
n FOLLOWING | 현재 행을 포함하여 이후 n개 행까지 |
UNBOUNDED FOLLOWING | 현재 행부터 파티션의 마지막 행까지 |
ROLLUP 혹은 CUBE 연산에서 생성된 소계 및 합계 행을 식별하기 위해 사용
SELECT 부서번호,
직책,
GROUPING(부서번호) AS 부서_그룹핑,
GROUPING(직책) AS 직책_그룹핑,
SUM(급여) AS 총급여
FROM 직원
GROUP BY ROLLUP(부서번호, 직책);
ROLLUP(a,b) = GROUPING SETS((a,b),(a),())
인자로 들어간 칼럼에 대해 모든 경우의 수로 부분합계
CUBE(a,b) = GROUPING SETS((a,b), (a), (b), ())
SELECT 열이름,
윈도우함수() OVER (PARTITION BY 그룹기준 ORDER BY 정렬기준)
FROM 테이블명;
PARTITION BY를 사용하여 그룹 내에서 순위 계산sql
복사편집
SELECT 이름, 부서, 급여,
RANK() OVER (PARTITION BY 부서 ORDER BY 급여 DESC) AS 부서별순위
FROM 직원;
PARTITION BY 부서를 사용하여 부서별로 그룹을 나눔ORDER BY 급여 DESC를 기준으로 부서별 순위 계산결과 예시
| 이름 | 부서 | 급여 | 부서별순위 |
|---|---|---|---|
| 김철수 | 영업부 | 6000 | 1 |
| 이민호 | 영업부 | 5200 | 2 |
| 박영희 | 마케팅부 | 5500 | 1 |
| 정하나 | 마케팅부 | 5000 | 2 |
PARTITION BY를 사용한 집계 함수 활용sql
복사편집
SELECT 이름, 부서, 급여,
SUM(급여) OVER (PARTITION BY 부서) AS 부서별급여총합,
AVG(급여) OVER (PARTITION BY 부서) AS 부서별평균급여
FROM 직원;
SUM(급여), AVG(급여) 값을 계산하여 각 행에 표시GROUP BY와 달리 개별 행을 유지하면서 부서별 급여 합계 및 평균을 구함결과 예시
| 이름 | 부서 | 급여 | 부서별급여총합 | 부서별평균급여 |
|---|---|---|---|---|
| 김철수 | 영업부 | 6000 | 11200 | 5600 |
| 이민호 | 영업부 | 5200 | 11200 | 5600 |
| 박영희 | 마케팅부 | 5500 | 10500 | 5250 |
| 정하나 | 마케팅부 | 5000 | 10500 | 5250 |
PARTITION BY와 ROWS BETWEEN을 활용한 누적 합계sql
복사편집
SELECT 이름, 부서, 급여,
SUM(급여) OVER (PARTITION BY 부서 ORDER BY 급여 DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 부서별누적급여
FROM 직원;
PARTITION BY 부서 → 부서별로 그룹을 나눔ORDER BY 급여 DESC → 급여가 높은 순서로 정렬ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW → 현재 행까지의 누적 합계 계산결과 예시
| 이름 | 부서 | 급여 | 부서별누적급여 |
|---|---|---|---|
| 김철수 | 영업부 | 6000 | 6000 |
| 이민호 | 영업부 | 5200 | 11200 |
| 박영희 | 마케팅부 | 5500 | 5500 |
| 정하나 | 마케팅부 | 5000 | 10500 |
PARTITION BY와 LAG, LEAD 함수 활용sql
복사편집
SELECT 이름, 부서, 급여,
LAG(급여) OVER (PARTITION BY 부서 ORDER BY 급여 DESC) AS 이전급여,
LEAD(급여) OVER (PARTITION BY 부서 ORDER BY 급여 DESC) AS 다음급여
FROM 직원;
LAG(급여) OVER (...) → 이전 행의 급여 가져오기LEAD(급여) OVER (...) → 다음 행의 급여 가져오기PARTITION BY 부서 → 부서별로 그룹을 나눔ORDER BY 급여 DESC → 급여가 높은 순서로 정렬결과 예시
| 이름 | 부서 | 급여 | 이전급여 | 다음급여 |
|---|---|---|---|---|
| 김철수 | 영업부 | 6000 | NULL | 5200 |
| 이민호 | 영업부 | 5200 | 6000 | NULL |
| 박영희 | 마케팅부 | 5500 | NULL | 5000 |
| 정하나 | 마케팅부 | 5000 | 5500 | NULL |
상위 N개의 데이터 조회
SELECT TOP 3 이름, 점수
FROM 학생
ORDER BY 점수 DESC;
점수가 높은 상위 N명 + 동일한 점수를 가진 추가 학생들까지 반환
SELECT TOP 3 WITH TIES 이름, 점수
FROM 학생
ORDER BY 점수 DESC;