SELECT 문은 데이터베이스에서 데이터를 조회하는 가장 기본적인 명령어다. 내부 파싱 순서는 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY 순으로 실행된다.
SELECT [DISTINCT] 컬럼명 [AS 별칭], 컬럼명 [별칭], 표현식, ...
FROM 테이블명 [별칭]
[WHERE 조건식]
[GROUP BY 그룹화할_컬럼명]
[HAVING 그룹_조건식]
[ORDER BY 정렬할_컬럼명 [ASC|DESC]]
* 사용 시 모든 컬럼 조회컬럼명 AS 별칭 또는 컬럼명 별칭SELECT empno, ename AS 이름, sal * 1.1 "인상된 급여"
FROM emp;
SELECT sysdate FROM dual; -- ORACLE에서 현재 날짜 조회
SELECT getdate(); -- SQL Server에서 현재 날짜 조회(FROM 절 생략)
데이터를 필터링하는 조건을 지정한다. 다양한 연산자를 사용할 수 있다.
=, >, >=, <, <=, <> (또는 !=) 등AND, OR, NOT-- 부서번호가 10이거나 20이면서 급여가 2000 이상인 직원
SELECT empno, ename, deptno, sal
FROM emp
WHERE (deptno = 10 OR deptno = 20) AND sal >= 2000;
-- 부서번호가 10, 20, 30 중 하나인 직원
SELECT empno, ename, deptno
FROM emp
WHERE deptno IN (10, 20, 30);
-- 급여가 2000에서 3000 사이인 직원
SELECT empno, ename, sal
FROM emp
WHERE sal BETWEEN 2000 AND 3000;
-- 이름이 S로 시작하는 직원
SELECT empno, ename FROM emp WHERE ename LIKE 'S%';
-- 이름의 두 번째 글자가 A인 직원
SELECT empno, ename FROM emp WHERE ename LIKE '_A%';
-- 커미션이 NULL인 직원
SELECT empno, ename, comm
FROM emp
WHERE comm IS NULL;
= 연산자 사용 불가, IS NULL/IS NOT NULL 사용해야 함-- NULL 처리 예시
SELECT ename, sal, comm, sal + comm "계산결과"
FROM emp; -- comm이 NULL인 행은 계산결과도 NULL
-- NULL 처리를 위한 NVL/COALESCE 함수 사용
SELECT ename, sal, comm, sal + NVL(comm, 0) "계산결과"
FROM emp; -- NULL을 0으로 변환하여 계산
결과를 정렬할 때 사용한다. SELECT 절의 마지막에 위치하며, 내부적으로도 가장 마지막에 수행된다.
ASC(기본값, 생략 가능)DESC-- 부서번호 오름차순, 같은 부서 내에서는 급여 내림차순 정렬
SELECT empno, ename, deptno, sal
FROM emp
ORDER BY deptno, sal DESC;
-- 별칭으로 정렬
SELECT empno, ename, sal*12 AS 연봉
FROM emp
ORDER BY 연봉 DESC;
-- 컬럼 위치로 정렬
SELECT empno, ename, deptno, sal
FROM emp
ORDER BY 3, 4 DESC; -- 3번째 컬럼(deptno) 오름차순, 4번째 컬럼(sal) 내림차순
NULLS FIRST / NULLS LAST 옵션으로 위치 지정 가능-- ORACLE에서 NULL 정렬 제어
SELECT ename, comm
FROM emp
ORDER BY comm NULLS FIRST; -- NULL을 맨 앞에 정렬
데이터를 그룹화하여 집계 함수를 적용할 때 사용한다.
-- 부서별 평균 급여
SELECT deptno, AVG(sal) 평균급여
FROM emp
GROUP BY deptno;
-- 부서별, 직무별 직원 수와 평균 급여
SELECT deptno, job, COUNT(*) 직원수, AVG(sal) 평균급여
FROM emp
GROUP BY deptno, job;
GROUP BY로 생성된 그룹에 조건을 적용할 때 사용한다.
-- 평균 급여가 2000 이상인 부서만 조회
SELECT deptno, AVG(sal) 평균급여
FROM emp
GROUP BY deptno
HAVING AVG(sal) >= 2000;
-- 직원이 3명 이상인 부서의 최대 급여
SELECT deptno, COUNT(*) 직원수, MAX(sal) 최대급여
FROM emp
GROUP BY deptno
HAVING COUNT(*) >= 3;
SQL에서는 다양한 내장 함수를 제공하여 데이터 처리를 돕는다.
UPPER(문자열): 대문자로 변환LOWER(문자열): 소문자로 변환INITCAP(문자열): 각 단어의 첫 글자만 대문자로 변환 (ORACLE)SELECT UPPER('hello'), LOWER('WORLD'), INITCAP('hello world') FROM dual;
-- 결과: HELLO, world, Hello World
LENGTH(문자열) / LEN(문자열): 문자열 길이 반환SUBSTR(문자열, 시작위치, 길이) / SUBSTRING(문자열, 시작위치, 길이): 부분 문자열 추출INSTR(문자열, 찾을문자열, [시작위치, [발생횟수]]) / CHARINDEX(찾을문자열, 문자열, [시작위치]): 문자열 위치 찾기SELECT LENGTH('hello world'), SUBSTR('hello world', 1, 5), INSTR('hello world', 'o') FROM dual;
-- 결과: 11, hello, 5
TRIM([LEADING|TRAILING|BOTH] [제거할문자] FROM 문자열): 문자열 앞/뒤의 공백 또는 특정 문자 제거LTRIM(문자열, [제거할문자들]): 왼쪽에서 문자 제거RTRIM(문자열, [제거할문자들]): 오른쪽에서 문자 제거REPLACE(문자열, 찾을문자열, 대체문자열): 문자열 치환SELECT TRIM(' hello '), LTRIM('xxxhello', 'x'), REPLACE('hello world', 'world', 'SQL') FROM dual;
-- 결과: hello, hello, hello SQL
CONCAT(문자열1, 문자열2) / 문자열1 || 문자열2 / 문자열1 + 문자열2: 문자열 연결SELECT CONCAT('hello', ' world') FROM dual;
-- 결과: hello world
ROUND(숫자, [소수자릿수]): 반올림TRUNC(숫자, [소수자릿수]) / TRUNCATE(숫자, [소수자릿수]): 절삭CEIL(숫자) / CEILING(숫자): 올림FLOOR(숫자): 내림SELECT ROUND(123.456, 2), TRUNC(123.456, 1), CEIL(123.1), FLOOR(123.9) FROM dual;
-- 결과: 123.46, 123.4, 124, 123
MOD(숫자1, 숫자2) / 숫자1 % 숫자2: 나머지ABS(숫자): 절대값POWER(숫자, 제곱수): 제곱SQRT(숫자): 제곱근SELECT MOD(10, 3), ABS(-10), POWER(2, 3), SQRT(16) FROM dual;
-- 결과: 1, 10, 8, 4
SYSDATE / GETDATE(): 현재 날짜와 시간SELECT SYSDATE FROM dual; -- 결과: 현재 날짜와 시간
ADD_MONTHS(날짜, 개월수) / DATEADD(month, 개월수, 날짜): 개월 수 더하기MONTHS_BETWEEN(날짜1, 날짜2) / DATEDIFF(month, 날짜2, 날짜1): 두 날짜 사이의 개월 수LAST_DAY(날짜): 해당 월의 마지막 날짜SELECT ADD_MONTHS(SYSDATE, 3), LAST_DAY(SYSDATE) FROM dual;
-- 결과: 현재로부터 3개월 후, 현재 월의 마지막 날짜
EXTRACT(YEAR|MONTH|DAY FROM 날짜) / DATEPART(year|month|day, 날짜): 날짜에서 년/월/일 추출SELECT EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE) FROM dual;
-- 결과: 현재 연도, 현재 월
TO_CHAR(날짜|숫자, 포맷) / CONVERT(varchar, 날짜|숫자, 포맷): 날짜나 숫자를 문자열로 변환TO_NUMBER(문자열, [포맷]) / CONVERT(numeric, 문자열): 문자열을 숫자로 변환TO_DATE(문자열, 포맷) / CONVERT(datetime, 문자열, 포맷): 문자열을 날짜로 변환SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD'), TO_CHAR(12345.67, '$999,999.99') FROM dual;
-- 결과: 2025-05-13, $12,345.67
SELECT TO_NUMBER('12,345.67', '99,999.99'), TO_DATE('2022-01-01', 'YYYY-MM-DD') FROM dual;
-- 결과: 12345.67, 2022년 1월 1일
NVL(값1, 값2) / ISNULL(값1, 값2): 값1이 NULL이면 값2 반환, 아니면 값1 반환NVL2(값, NULL아닐때값, NULL일때값): 값이 NULL이 아니면 두번째 인수, NULL이면 세번째 인수 반환NULLIF(값1, 값2): 두 값이 같으면 NULL, 다르면 값1 반환COALESCE(값1, 값2, ...): NULL이 아닌 첫 번째 값 반환-- 커미션이 NULL이면 0으로 대체
SELECT ename, NVL(comm, 0) FROM emp;
-- 커미션이 있으면 O, 없으면 X
SELECT ename, NVL2(comm, 'O', 'X') 커미션유무 FROM emp;
-- NULL이 아닌 첫 번째 값 반환
SELECT COALESCE(NULL, NULL, 'Hello', 'World') FROM dual; -- 결과: Hello
DECODE(컬럼/표현식, 조건1, 결과1, 조건2, 결과2, ..., 기본값): 조건에 따른 결과 반환(ORACLE)CASE WHEN 조건1 THEN 결과1 [WHEN 조건2 THEN 결과2 ...] [ELSE 기본값] END: 조건에 따른 결과 반환-- 부서번호에 따라 부서명 출력
SELECT ename, DECODE(deptno, 10, 'Accounting', 20, 'Research', 'Other') FROM emp;
-- 급여에 따라 등급 출력
SELECT ename,
CASE
WHEN sal >= 3000 THEN 'High'
WHEN sal >= 2000 THEN 'Medium'
ELSE 'Low'
END 급여등급
FROM emp;
그룹 함수는 여러 행을 입력으로 받아 하나의 결과를 반환한다. NULL 값은 연산에서 제외된다.
COUNT(컬럼|*): 행의 수 반환 (NULL 제외, COUNT(*) 제외)SUM(컬럼): 합계AVG(컬럼): 평균MAX(컬럼): 최대값MIN(컬럼): 최소값SELECT
COUNT(*) 직원수,
SUM(sal) 급여합계,
AVG(sal) 평균급여,
MAX(sal) 최대급여,
MIN(sal) 최소급여
FROM emp;
STDDEV(컬럼) / STDEV(컬럼): 표준편차VARIANCE(컬럼) / VAR(컬럼): 분산SELECT STDDEV(sal), VARIANCE(sal) FROM emp;
| 기능 | ORACLE | SQL Server |
|---|---|---|
| 현재 날짜 조회 | SYSDATE | GETDATE() |
| FROM 절 생략 | 불가능 (DUAL 사용) | 가능 |
| 문자열 연결 | CONCAT(str1, str2) 또는str1 || str2 | CONCAT(str1, str2) 또는str1 + str2 |
| 날짜 더하기 | ADD_MONTHS(date, n) | DATEADD(month, n, date) |
| 날짜 간격 | MONTHS_BETWEEN(date1, date2) | DATEDIFF(month, date2, date1) |
| NULL 위치 정렬 | ORDER BY col NULLS FIRST\|LAST(기본: NULLS LAST) | 옵션 없음 (기본: NULLS FIRST) |
| 문자열 길이 | LENGTH(str) | LEN(str) |
| 부분 문자열 추출 | SUBSTR(str, pos, len) | SUBSTRING(str, pos, len) |
| 문자열 위치 찾기 | INSTR(str, substr, [pos, [occur]]) | CHARINDEX(substr, str, [pos]) |
| 조건부 결과 | DECODE(expr, search1, result1, ...) | CASE 문 사용 |
| NULL 치환 | NVL(expr, replace_value) | ISNULL(expr, replace_value) |
| 숫자 절삭 | TRUNC(num, [digits]) | FLOOR(num) (소수점 없이)ROUND(num, digits, 1) (자릿수 지정) |
| 특수 JOIN 구문 | FROM tab1, tab2 WHERE tab1.col(+) = tab2.col(LEFT OUTER JOIN) | 지원 안함 (ANSI 구문 사용) |
| 페이징 처리 | ROWNUM 사용 또는FETCH FIRST n ROWS ONLY (12c 이상) | TOP n 구문 |
| 변환 함수 | TO_CHAR, TO_DATE, TO_NUMBER | CONVERT |
| 표준편차 | STDDEV | STDEV |
| 분산 | VARIANCE | VAR |
| 테이블 별칭 | FROM table alias (AS 생략) | FROM table AS alias (AS 선택) |
날짜 함수:
-- ORACLE
SELECT SYSDATE, ADD_MONTHS(SYSDATE, 3), MONTHS_BETWEEN('01-JAN-2022', '01-OCT-2021') FROM dual;
-- SQL Server
SELECT GETDATE(), DATEADD(month, 3, GETDATE()), DATEDIFF(month, '2021-10-01', '2022-01-01');
변환 함수:
-- ORACLE
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD'), TO_DATE('2022-01-01', 'YYYY-MM-DD') FROM dual;
-- SQL Server
SELECT CONVERT(varchar, GETDATE(), 120), CONVERT(datetime, '2022-01-01', 120);
NULL 처리:
-- ORACLE
SELECT NVL(comm, 0), NVL2(comm, 'O', 'X') FROM emp;
-- SQL Server
SELECT ISNULL(comm, 0), CASE WHEN comm IS NOT NULL THEN 'O' ELSE 'X' END FROM emp;
OUTER JOIN:
-- ORACLE (오래된 문법)
SELECT e.ename, d.dname
FROM emp e, dept d
WHERE e.deptno(+) = d.deptno; -- RIGHT OUTER JOIN
-- SQL Server (ANSI 표준 문법)
SELECT e.ename, d.dname
FROM dept d LEFT OUTER JOIN emp e ON d.deptno = e.deptno;
TOP N 쿼리:
-- ORACLE
SELECT * FROM (
SELECT * FROM emp ORDER BY sal DESC
) WHERE ROWNUM <= 5;
-- ORACLE 12c 이상
SELECT * FROM emp
ORDER BY sal DESC
FETCH FIRST 5 ROWS ONLY;
-- SQL Server
SELECT TOP 5 * FROM emp
ORDER BY sal DESC;