SQL에서 CRUD를 담당하는 DML(SELECT, INSERT, UPDATE, DELETE) 중에서 데이터를 추출하기 위해 사용되는 언어를 DQL(SELECT)라고 한다
데이터를 조회한 결과로 0개 이상의 행을 포함하는 RESULT SET을 갖는다
SELECT 컬럼명 (,컬럼명...) FROM 테이블명 WHERE 조건
*
: 모든 컬럼을 다 보고 싶을 때
테이블에 없는 데이터도 산술식을 통해 가져올 수 있다
-- 주석
-- 직원 테이블에서,
-- 이름, 이메일, 전화번호, 월급을 보여줘
-- 월급이 250만원 이상인 직원
SELECT EMP_NAME, EMAIL, PHONE, SALARY FROM EMPLOYEE WHERE SALARY>=2500000;
SELECT문을 작성할 때 컬럼에 별칭을 줄 수 있다
SELECT EMP_NAME AS "이름", SALARY "월급", SALARY*12 연봉,
--1. AS "별칭" 2. "별칭"
(SALARY+(SALARY*BONUS))*12"연봉(보너스포함)" FROM EMPLOYEE;
--3. 별칭만
지정한 문자열을 리터럴로 가진 단위 컬럼을 만들 수 있다
SELECT EMP_NAME, SALARY,'원' 단위 FROM EMPLOYEE;
-- '원'=값자체 리터럴
-- 월급에 단위를 붙여주기 위한 리터럴
DISTINCT
SELECT DISTINCT JOB_CODE FROM EMPLOYEE;
-- 컬럼에 포한됨 중복값을 한번씩만 표시
||
: 여러컬럼을 하나의 컬럼인 것처럼 연결 || 컬럼과 리터럴을 연결
SELECT EMP_NAME, SALARY+'원' FROM EMPLOYEE;
-- JAVA처럼 +연산자로 붙여줄 수 없다
SELECT EMP_NAME, SALARY||'원' FROM EMPLOYEE;
-- 8000000원
SELECT EMP_ID||EMP_NAME FROM EMPLOYEE;
-- 컬럼이 하나의 컬럼처럼 붙어서 출력
AND
: 여러조건이 동시에 TRUE일 경우 TRUE
OR
: 여러조건 중 하나라도 TRUE일 경우 TRUE
NOT
: 조건에 대한 반대로 반환 (NULL제외)
TRUE / FALSE / NULL 결과 반환
SELECT 비교연산자 | |
---|---|
= | |
>, < | |
>=, =< | |
<>, !=, ^= | 같지 않다 |
BERWEEN A AND B | 특정범위에 포함되는지 비교 |
LIKE, NOT LIKE | 문자 패턴 비교 |
IS NULL, IS NOT NULL | NULL 여부 비교 |
IN, NOT IN | 비교 값 목록에 포함/미포함 |
비교하려는 값이 특정 패턴을 만족시키면 TRUE 리턴
※ 와일드카드
%
: 글자수 제한없이 퍼센트 하나로 대체
_
: 한 글자 대체 (글자수만큼 _)
ESCAPE : 와일드 카드를 예외처리 해준다 (JAVA의 '\' )
WHERE EMP_NAME LIKE '전__';
WHERE EMP_NAME LIKE '전%';
-- 성이 '전'인 사람 조회
WHERE EMAIL LIKE '___#_%'ESCAPE'#';
-- 이메일 4번째 글자가 _인 사람 조회
-- '#'뒤에 글자는 와일드카드가 아니라는 의미
-- 비어있는지, 아닌지
SELECT EMP_NAME, BONUS FROM EMPLOYEE WHERE BONUS IS NULL;
-- 이름, 부서코드 부서코드가 D9 또는 D6 또는 D8
SELECT EMP_NAME, DEPT_CODE FROM EMPLOYEE
WHERE DEPT_CODE NOT IN ('D9','D6','D8');
※ 연산순서
산술 > 연결 > 비교 > IS/LIKE > BETWEEN >NOT > AND > OR
SELECT EMP_NAME, DEPT_CODE, DEPT_TITLE
FROM EMPLOYEE CROSS JOIN DEPARTMENT;
-- 모든 DEPT_TITLE과 한 번씩 매치
SELECT E1.EMP_NAME "사원명", DEPT_TITLE "부서명", E2.EMP_NAME "동료이름"
FROM EMPLOYEE E1
JOIN DEPARTMENT ON (DEPT_ID = DEPT_CODE)
JOIN EMPLOYEE E2 ON (E1.DEPT_CODE = E2.DEPT_CODE)
WHERE E1.EMP_NAME NOT IN E2.EMP_NAME
ORDER BY 1;
-- 다중조인 + SELF JOIN
SELECT E1.EMP_NAME "사원명", DEPT_TITLE "부서명", E2.EMP_NAME "동료이름"
FROM EMPLOYEE E1
JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID)
JOIN EMPLOYEE E2 ON (E1.DEPT_CODE = E2.DEPT_CODE)
WHERE E1.EMP_NAME != E2.EMP_NAME
ORDER BY 1;
집합연산자
여러 개의 테이블에서 JOIN을 사용하지 않고 연관된 데이터를 조회하는 방법
여러 개의 조회결과를 결합하는 방식
JOIN은 컬럼을 추가하여 추가 데이터를 표현, 집합연산자는 ROW를 추가하여 추가 데이터를 표현
<성립 조건>
SELECT문 안에 또다른 SELECT문을 포함
서브쿼리는 메인 쿼리 실행 전 한 번만 실행
<서브쿼리 조건>
<서브쿼리 유형>
단일행 서브쿼리
ex ) 전직원의 평균급여보다 많은 급여를 받는 직원의 사번, 이름, 급여 조회
다중행 서브쿼리
ex ) 부서별 최고 급여를 받는 직원의 이름, 직급, 부서, 급여 조회
SELECT EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY IN (SELECT MAX(SALARY) FROM EMPLOYEE GROUP BY DEPT_CODE);
다중열 서브쿼리
다중행 다중열 서브쿼리
상관 서브쿼리 (상호연관 서브쿼리)
스칼라 서브쿼리
EX ) 모든 사원의 사번, 이름, 관리자 번호, 관리자이름 조회
SELECT EMP_ID, EMP_NAME, MANAGER_ID,
(SELECT E2.EMP_NAME FROM EMPLOYEE E2 WHERE E2.EMP_ID = E1.MANAGER_ID) AS 관리자명
FROM EMPLOYEE E1;
뷰 : 가상의 테이블
인라인 뷰 : FROM에서 사용하는 서브쿼리
SELECT * -- 가상의 테이블에 포함한 컬럼만 조회 가능
FROM (SELECT EMP_NAME, DEPT_CODE, JOB_CODE, SALARY FROM EMPLOYEE);
SELECT ROWNUM, EMP_NAME, DEPT_CODE, SALARY
FROM (SELECT EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE ORDER BY SALARY DESC)
WHERE ROWNUM<6;
-- ROWNUM : 컬럼 앞에 붙는 번호를 컬럼처럼 사용하도록 한다
----------------------------------------------------------------
SELECT ROWNUM, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE ORDER BY SALARY DESC;
-- 그냥 ROWNUM할 경우 ORDER BY가 가장 늦게 동작하기 때문에
-- SALARY기준이 틀어진다
-- 먼저 SALARY정렬 기준으로 내림차순 한 테이블을 만들어 둔 다음
-- 해당 테이블에 ROWNUM을 붙여준다
----------------------------------------------------------------
SELECT EMP_NAME, SALARY,
RANK() OVER(ORDER BY SALARY DESC)
FROM EMPLOYEE;
SELECT EMP_NAME, SALARY,
DENSE_RANK() OVER(ORDER BY SALARY DESC)
FROM EMPLOYEE;
SELECT EMP_NAME, SALARY,
ROW_NUMBER() OVER(ORDER BY SALARY DESC)
FROM EMPLOYEE;
RANK() OVER(ORDER BY 컬럼 DESC) :
같은 순위가 2일 때 다음 순위 +1DENSE_RANK() OVER(ORDER BY 컬럼 DESC) :
같은 순위가 2일 때 다음 순위 바로 연결ROW_NUMBER() OVER(ORDER BY 컬럼 DESC)
같은 순위 무시하고 연결