SQL (1)

1. SELECT

-- 실행순서: FROM 절 -> SELECT 절
SELECT fieldnames
FROM tablename;


-- field의 가공처리
SELECT empno, ename, sal+100 
FROM scott_emp;
-- field alias
SELECT empno, ename, mgr manager FROM scott_emp;
SELECT empno, ename, mgr as manager FROM scott_emp;
SELECT empno, ename, mgr as 'my manager' FROM scott_emp;
-- 중복 제거: distinct
SELECT distinct job 
FROM scott_emp;


2. 확장 문법

2.1. 정렬 기능: ORDER BY

-- 실행순서: FROM 절 -> SELECT 절 -> ORDER BY 절
-- **Note: 정렬 기능은 항상 제일 마지막에**
SELECT fieldnames
FROM tablename
ORDER BY fieldnames;


-- 급여가 많은 순으로 이름, 급여, 부서코드를 조회
SELECT ename, sal, deptno 
FROM scott_emp
ORDER BY sal DESC;
-- 부서별로 급여가 적은 순으로 이름, 급여, 부서코드 조회
SELECT ename, sal, deptno 
FROM scott_emp
ORDER BY deptno, sal;


2.2. 조건 기능 (레코드 필터링): WHERE

-- 실행순서: FROM 절 -> WHERE 절 -> SELECT 절
SELECT fieldnames
FROM tablename
WHERE blah blah


-- 급여가 3000$ 이상인 직원의 사번, 이름, 급여를 조회
SELECT empno, ename, sal 
FROM scott_emp
WHERE sal >= 3000;
-- 업무가 manager인 직원의 이름, 부서, 업무, 급여 조회
SELECT empno, ename, sal 
FROM scott_emp
WHERE job = 'manager';
-- 부서가 20이고 업무가 analyst인 직원의 이름, 부서, 업무, 급여 조회
SELECT ename, deptno, job, sal 
FROM scott_emp
WHERE deptno = 20 AND job = 'Analyst';


-- 급여가 1500 이상 2500 미만을 받는 직원의 이름, 부서, 업무 급여를 조회 (단, 급여가 많은 순으로 조회)
SELECT ename, deptno, job, sal 
FROM scott_emp
WHERE sal >= 1500 AND sal <= 2000
ORDER BY sal DESC;

-- !!Note: BETWEEN AND는 '이상, 이하' 일 때만 쓸 수 있음
SELECT ename, deptno, job, sal 
FROM scott_emp
WHERE sal BETWEEN 1500 AND 2000;


-- 업무가 clerk, salesman, analyst인 직원의 이름, 부서, 업무, 급여 조회
SELECT ename, deptno, job, sal 
FROM scott_emp
WHERE job = 'clerk' OR job = 'salesman' OR job = 'analyst';

-- !!Note: IN은 'OR 조건' 일 때만 쓸 수 있음
SELECT ename, deptno, job, sal 
FROM scott_emp
WHERE job IN ('clerk', 'salesman', 'analyst');


-- 1982/01/01 이후에 입사한 직원의 이름, 업무, 입사일자 조회
-- Note: SQL에서 날짜는 문자열 형식, 날짜형식만 유지하면 구분자는 상관없음
SELECT ename, job, hiredate 
FROM scott_emp
WHERE hiredate > '1982-01-01';
WHERE hiredate > '1982/01/01';
WHERE hiredate > '1982,01,01';


-- 커미션이 없는 직원의 이름, 부서, 업무, 급여, 커미션 조회
SELECT ename, empno, job, sal, comm 
FROM scott_emp
WHERE comm IS null;


-- 커미션이 있는 직원
SELECT ename, empno, job, sal, comm 
FROM scott_emp
WHERE comm IS NOT null;

SELECT ename, empno, job, sal, comm 
FROM scott_emp
WHERE comm >= 0;


2.3. Like 연산자

  • % : 0개 이상의 문자 대체
  • _ : 1개 문자 대체
  • 예시: beau% - beau, beaut, beauti, ..
  • 예시: beau__ - beauab, beauti, beaufl ..
-- 이름이 s로 끝나는 직원의 이름, 업무, 급여를 조회
SELECT ename, job, sal 
FROM scott_emp
WHERE ename like '%s';
+-------+---------+------+
| ename | job     | sal  |
+-------+---------+------+
| JONES | MANAGER | 2975 |
| ADAMS | CLERK   | 1100 |
| JAMES | CLERK   |  950 |
+-------+---------+------+


2.4. GROUP BY & HAVING 조건

  • Group by 절: 특정 컬럼 값을 기준으로 그룹화
  • Having 절: 그룹으로 묶은 뒤, 조건이 있는 경우
-- 부서별로 급여 평균, 최저 급여 조회 (급여 평균이 높은 순으로)
-- 실행순서: FROM -> GROUP BY ->SELECT -> ORDER BY
SELECT deptno, round(avg(sal)), round(min(sal))
FROM scott_emp
GROUP BY deptno
ORDER BY avg(sal) DESC;
+--------+-----------------+-----------------+
| deptno | round(avg(sal)) | round(min(sal)) |
+--------+-----------------+-----------------+
|     10 |            2917 |            1300 |
|     20 |            2175 |             800 |
|     30 |            1567 |             950 |
+--------+-----------------+-----------------+


-- 전체 급여의 합계가 5000을 초과하는 업무에 대해서 급여 합계 조회 (deptno로 정렬)
-- 실행순서: FROM -> GROUP BY -> HAVING -> SELECT -> ORDER BY
SELECT job, sum(sal) 
FROM scott_emp  /* WHERE sum(sal) > 5000 오류발생 */
GROUP BY job
HAVING sum(sal) > 5000 
ORDER BY deptno;
+----------+----------+
| job      | sum(sal) |
+----------+----------+
| ANALYST  |     6000 |
| MANAGER  |     8275 |
| SALESMAN |     5600 |
+----------+----------+
-- 전체 급여의 합계가 5000을 초과하는 업무에 대해서 급여 합계 조회 (단, salesman 제외)
SELECT job, sum(sal) 
FROM scott_emp
GROUP BY job
HAVING sum(sal) > 5000 AND job <> 'salesman';

-- 성능 더 좋음
SELECT job, sum(sal) 
FROM scott_emp
WHERE job <> 'salesman'
GROUP BY job
HAVING sum(sal) > 5000;
+---------+----------+
| job     | sum(sal) |
+---------+----------+
| ANALYST |     6000 |
| MANAGER |     8275 |
+---------+----------+


3. 함수

3.1. Single-Row Function (단일행 함수)

String Function:

  • ASCII( ), CHAR()
  • LENGTH()
  • INSTR()
  • LEFT(), RIGHT(), SUBSTR(), SUBSTRING()
SELECT ASCII('a');
	--> 97
SELECT CHAR(98);
	--> b

SELECT LENGTH(ename) FROM scott_emp;

-- Note: SQL의 문자열 index는 1부터 시작
SELECT INSTR('foobarbar', 'bar');
	--> 4
SELECT INSTR('foobarbar', 'love');
	--> 0

SELECT LEFT('abcdefg', 3);
	--> abc
SELECT RIGHT('abcdefg', 4);
	--> defg
SELECT SUBSTRING('i lovee SQL', 3);
	--> lovee SQL
SELECT SUBSTRING('i lovee SQL', 3, 4);
	--> love
SELECT SUBSTRING('i lovee sql', -3);
	--> sql
SELECT SUBSTRING('i lovee sql', -9, 5);
	--> lovee


Numeric Function

  • CEIL(), FLOOR(), ROUND(), TRUNCATE()
  • MOD()
  • RAND()
SELECT CEIL(1.23);
	--> 2
SELECT FLOOR(1.73);
	--> 1

SELECT ROUND(1.23), ROUND(1.73);
	--> 1 | 2
SELECT ROUND(1.298, 1);
	--> 1.3

SELECT TRUNCATE(1.73, 0);
	--> 1


Date Function

-- NOW(), SYSDATE(), CURDATE(), CURTIME()
SELECT NOW();

-- YEAR(), MONTH(), DAYOFMONTH()
SELECT YEAR(NOW()), MONTH(NOW());

-- DAYOFWEEK(): 1-일요일, WEEKDAY(): 0-월요일
SELECT DAYOFWEEK(NOW()), WEEKDAY(NOW());

-- DAOFYEAR(): 1년 중 며칠이 지났는지 알려줌
SELECT DAYOFYEAR(NOW());

-- DATE_ADD(), DATE_SUB()
SELECT DATE_ADD(NOW(), interval 5 YEAR), DATE_ADD(NOW(), interval 5 DAY);


3.2. Aggregation Function

SUM(), AVG(), COUNT(), MAX(), MIN()

3.3. 기타

CONVERT(), CASE(), COALESCE()

-- CONVERT()
SELECT CONVERT('2019-5-1', DATE);
SELECT CONVERT(150, CHAR);
SELECT CONVERT('14:06:10', TIME);
-- CASE()
-- 업무가 salesman이면 'yes' 이라고하고, 그 외 업무는 'no' 라고 조회
SELECT ename, job, comm,
	CASE 
		WHEN job = 'salesman' THEN 'yes'
		ELSE 'no'
	END iscomm
FROM scott_emp;
+--------+-----------+--------+
| ename  | comm      | iscomm |
+--------+-----------+--------+
| SMITH  | CLERK     | no     |
| ALLEN  | SALESMAN  | yes    |
| WARD   | SALESMAN  | yes    |
| JONES  | MANAGER   | no     |
| MARTIN | SALESMAN  | yes    |
| BLAKE  | MANAGER   | no     |
| CLARK  | MANAGER   | no     |
| SCOTT  | ANALYST   | no     |
| KING   | PRESIDENT | no     |
| TURNER | SALESMAN  | yes    |
| ADAMS  | CLERK     | no     |
| JAMES  | CLERK     | no     |
| FORD   | ANALYST   | no     |
| MILLER | CLERK     | no     |
+--------+-----------+--------+
-- COALESCE()
-- 현재 직원들의 총 급여를 조회
SELECT empno, ename, sal, comm, (sal + comm) as total FROM scott_emp; 

--null값 처리
SELECT empno, ename, sal, comm,
	(sal + COALESCE(comm, 0)) as total
	FROM scott_emp;
+-------+--------+------+------+-------+
| empno | ename  | sal  | comm | total |
+-------+--------+------+------+-------+
|  7369 | SMITH  |  800 | NULL |   800 |
|  7499 | ALLEN  | 1600 |  300 |  1900 |
|  7521 | WARD   | 1250 |  500 |  1750 |
|  7566 | JONES  | 2975 | NULL |  2975 |
|  7654 | MARTIN | 1250 | 1400 |  2650 |
|  7698 | BLAKE  | 2850 | NULL |  2850 |
|  7782 | CLARK  | 2450 | NULL |  2450 |
|  7788 | SCOTT  | 3000 | NULL |  3000 |
|  7839 | KING   | 5000 | NULL |  5000 |
|  7844 | TURNER | 1500 |    0 |  1500 |
|  7876 | ADAMS  | 1100 | NULL |  1100 |
|  7900 | JAMES  |  950 | NULL |   950 |
|  7902 | FORD   | 3000 | NULL |  3000 |
|  7934 | MILLER | 1300 | NULL |  1300 |
+-------+--------+------+------+-------+