본문 바로가기

Computer/DATABASE

SQL 기본 지침서

SQL = sequel , Structured Query Language

 

SQL문 작성 규칙 및 지침

구문에서는 대소문자 구분 없음.

공백의 사용 - 하나 이상의 줄에 입력할 수 있음.

문의 종결 - ;(세미콜론)을 사용하여 문장을 종료함

 

산술 연산자 사용

 

연산자

설명

우선순위

* 또는 /

곱하기/나누기

1

+ 또는 -

더하기/빼기

2

우선 순위가 동일할떈 왼쪽에서 오른쪽으로, 괄호는 무조건 우선 순위 연산 수행

 

 

DDL(Data Definition Language)

DML(Data Manipulation Language)

DCL(Data Control Language)

 

명령문

구분

설명

SELECT

데이터 검색

데이터베이스에서 데이터를 검색

INSERT

UPDATE

DELETE

MERGE

DML(데이터 조작어)

데이터베이스의 테이블에서 새 행(Row) 입력, 기존 행 변경 및 필요 없는 행 제거를 수행

CREATE

ALTER

DROP

RENAME

TRUNCATE

DDL(데이터 정의어)

테이블에서 데이터 구조를 설정, 변경 및 제거

COMMIT

ROLLBACK

SAVEPOINT

트랜잭션(Transaction) 제어

DML 문이 변경한 내용을 관리, 데이터에 대한 변경은 논리적인 트랜잭션으로 그룹화 될 수 있음

GRANT

REVOKE

DCL(데이터 제어어)

오라클 데이터베이스 및 해당 구조에 대한 액세스(Access) 권한을 부여하거나 제거

SQL SELECT

SQL WHERE 절의 사용

WHERE 절 연산자

IN 연산자의 사용

NOT 연산자의 사용

LIKE 연산자의 사용

와일드 카드 사용 팁

 

 

 

=============================================

SQL SELECT

 

 

SELECT [DISTINCT] * or 열 이름 or 열 이름 as [ ALIAS]

FROM 테이블

WHERE 조건

ORDER BY expr [ASC DESC] ;

 

 

* SELECT * FROM table_name;

- table_name 테이블의 모든 내용을 보여준다.

 

* SELECT field_name1, fieldname2 FROM table_name;

- table_name 테이블에서 field_name1, field_name2 필드의 내용을 보여준다.

 

* SELECT * FROM table_name ORDER BY field_name [DESC];

- table_name 테이블의 모든 내용을 field_name 필드의 값에 의해 정렬해서 가져온다.

- DESC를 붙이면 내림차순, 붙이지 않으면 오름차순이다.

 

* SELECT * FROM table_name WHERE field_name = 'content';

- table_name 테이블의 field_name 값이 content인 테이터들을 불러온다.

 

* SELECT * FROM table_name WHERE field_name LIKE '%me%';

- table_name 테이블의 field_name 값이 me를 포함하고 있는 데이터들을 불러온다.

 

 

 

 

 

 

 

 

--문제. 전체 사원에 대한 정보를 출력하시오.

SELECT *

FROM emp

 

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO

 

EMPNO => 사원번호(PK 고유 값 > UNIQUE + NOT NULL)

ENAME => 사원이름

JOB => 직업(직무)

MGR => 선임매니져 사원번호

HIREDATE => 입사일

SAL => 급여

COMM => 상여급

DEPTNO => 부서번호

 

 

 

--문제1. 사원명, 급여, 급여에 100을 더한 보너스 합산, 급여의 10%인 세금을 출력하라.

SELECT emp.ename AS 사원명, emp.sal AS 급여, emp.sal+100 AS 보너스합산, emp.sal*0.1 AS 세금

FROM emp

 

 

--문제2. 사원번호가 7900인 사람의 사원명, 사원번호 출력하라.

SELECT emp.ename AS 사원명, emp.empno AS 사원번호

FROM emp

WHERE empno=7900

 

 

--문제3. 사원명이 JAMES 의 모든 정보 출력하라.

SELECT *

FROM emp

WHERE ename='JAMES'

 

== " " => 엘리어스 지정할 때만.

== ' ' => 테이블 내부의 모든 값. 객체들의 문자값을 처리할 때만.

== => 숫자값 처리할 때만.

 

 

--문제4. 전체 사원 중 DEPTNO30이면서 JOBSALESMAN인 사원을 출력하라.

SELECT *

FROM emp

WHERE (deptno=30

OR job='PRESIDENT')

AND deptno = 10

 

 

--문제5. 급여가 10001500사이의 직원 이름과 금여액을 구하라.

SELECT ename 이름, sal 급여액

FROM emp

WHERE sal BETWEEN 1000 AND 1500

(WHERE sal <=1500 AND sal >=1000)

 

 

--문제6. 이름이 B~G로 시작되는 사원의 이름을 출력하라.

SELECT ename 이름

FROM emp

WHERE ename BETWEEN 'B' AND 'G'

 

 

--문제7. 부서번호가 10 또는 20인 직원의 이름과 직책을 조회하라. (IN은 복수 함수가능)

SELECT ename 이름, job 직책

FROM emp

WHERE deptno IN(10,20,30)

 

 

--문제8. 이름이 S로 시작하는 직원을 조회하라.

SELECT * FROM emp

WHERE ename LIKE '%S%'

 

 

--문제9. 끝에서 2번째 자리에 문자가 E인 사람을 구하라.(와일드카드 %,_)

SELECT * FROM emp

WHERE ename LIKE '%E_'

 

 

--문제10. MANAGERNULL인 사람을 구하라.

NULL => 공간확보를 만들어놓기 위한 하나의 자리일뿐 어떠한 타입도 갖지 않는 곳

SELECT * FROM emp

WHERE mgr IS NULL

 

 

--문제11. 전체 사원의 이름, SAL, COMM, SAL+COMM 값을 출력하라.

SELECT ename, sal, comm, sal + NVL(comm,0)

FROM emp

NVL(A,B) => A에 널 값이 있으면, B에 있는 값으로 대처

 

 

--문제12. 부서번호가 10, 20이 아닌 사원명과 부서번호를 출력하라.

SELECT ename 사원명, deptno 부서번호

FROM emp

WHERE deptno NOT IN(10,20)

 

 

--문제 13. 급여가 10002900 사이를 제외한 사원의 이름과 급여를 출력하라.

SELECT ename 이름, sal 급여

FROM emp

WHERE sal NOT BETWEEN 1000 AND 2900

 

 

--문제14. 문제 급여에 낮은 순서대로 사원 정보를 출력하라. ORDER BY [DESC, ASC]

SELECT * FROM emp

ORDER BY sal DESC, hiredate ASC

 

 

--문제15. 전체 사원의 인원을 구하라.

SELECT COUNT(*) FROM emp

 

 

--문제16. 부서번호가 10인 사원의 인원을 구하라.

SELECT COUNT(*) FROM emp

WHERE deptno = 10

 

 

--문제17. 각 부서별 사원 수를 구하라.

 

 

DEPTNO COUNT(*)

10 3

20 3

30 6

 

 

SELECT deptno,COUNT(*)

FROM emp

GROUP BY deptno

ORDER BY deptno

 

 

--문제18. 각 직업별로 SAL의 평균을 구하라.

SELECT job, AVG(sal)

FROM emp

GROUP BY job

 

 

--문제19. SAL3000 이상인 사람들의 직업과 평균을 구하라.

SELECT job, AVG(sal)

FROM emp

GROUP BY job

HAVING AVG(sal) >=3000

 

(GROUP 함수에는 WHERE 아닌 HAVING 사용)

 

 

DB 생성 : create database db;

DB 목록보기 : show databases;

DB 삭제 : drop database db;

 

 

 

테이블 생성 : create table 테이블명(필드명1 타입1, 필드명2 타입2,PRIMARY KEY(필드명));

테이블 목록보기 : show tables;

테이블 구조보기 : desc 테이블명;

테이블 필드변경 : alter table을 사용

ex)alter table 테이블명 add 새로운필드명 타입 [first 또는 after 필드명]; (새로운 필드 삽입, 다른건 윗글참조)

테이블 삭제 : drop table 테이블명;

 

 

 

 

 

 

Products 테이블

 

[SELECT ]

 

현재 사용자가 가진 테이블 목록을 보여줌

 

* : 선택한 테이블의 모든 컬럼을 출력

기본순서대로 출력이 됨

---------------------------------------

select 원하는컬럼명

from 범위;

-----------------------------------------

select department_id, location_id

from departments;

-----------------------------------------

 

 

 

 

 

[사칙연산]

 

+ , - , *, / 사용가능

---------------------------------------

select salary+300

from employees;

---------------------------------------

 

사칙연산의 우선순위는 일반적인 우선순위와 같다.

---------------------------------------

select 12*salary+100

from employees;

---------------------------------------

select 12*(salary+100)

from employees;

---------------------------------------

 

 

 

 

[null ]

산술표현식에 null값이 포함되어 있는 경우는 결과가 모두 null이다.

100 + null = null

100 - null = null

100 * null = null

100 / null = null

 

 

 

 

 

 

[컬럼의 Alias 정의]

컬럼에 새로운 또 하나의 이름을 붙여주기

컬럼표현식이 그대로 나오지 않고,

표현식의 결과를 출력할때 지정한 이름으로 출력함

 

----------------------------------------

select 컬럼명 [as] alias

from 범위;

----------------------------------------

컬럼명 AS alias

컬럼명 alias

컬럼명 [AS] "Alias"

 

----------------------------------------

select last_name as name, department_id "department id"

from employees;

----------------------------------------

 

as 키워드는 옵션이며 생략가능함

기본적으로 대문자로 출력됨

대소문자 구분, 공백이나 특수문자 포함하는 경우 " " 사용

 

 

 

q operator :

single quotation을 포함하는 문자열을 출력할때 사용

', it''s Mgr ID : '

: double single quotationsingle quotation 하나의 문자로 인식함

==

q ' [ it's Mgr ID : ] '

: 10g이후로 추가된 방법. 위의 표현식과 결과 동일하다.

 

 

 

 

[concatenation operator]

컬럼과 컬럼을 연결하여 보여주는 연산자

|| 을 사용

 

 

 

select last_name || job_id as "Employees"

from employees;

-----------------------------------------

select last_name || ' is a ' || job_id as "Employees"

from employees;

-----------------------------------------

문자 표현을 덧붙일수 있다. ' ' 사용

 

 

 

 

 

 

 

 

[ distinct ]

컬럼의 중복값을 제거하고 출력

) 사원들의 부서를 출력할때 같은 부서의 이름은 제거하고 결국 부서 종류만을 볼수 있다.

 

select distinct 컬럼명

from 범위;

 

 

 

DISTINCT 이후에 모두 적용됨.

부서id와 잡 id의 조합의 값에서 중복을 제거하고 출력해줌.

 

출력하기위해 distinct는 중복을 제거하기위해 내부적으로 정렬과정을 거친다.

중복제거를 위한 과정이 추가되기 때문에 속도가 늦을 수가 있다.

 

중복제거요청 -> 정렬 -> 중복제거 -> 출력

 

 

 

-- 쿼리문의 구조

SELECT first_name

, last_name

FROM employees;

 

--

 

SELECT employee_id

, last_name

, salary

FROM employees

WHERE employee_id = 100;

 

--

 

SELECT *

FROM employees

WHERE employee_id = 100;

 

-- 테이블 컬럼 확인

DESC employees;

 

-- emp last_name'Austin', 'Chen'인 사원의 정보를 얻어보자.

-- 출력 결과> 사번, last_name, job_id, salary

SELECT employee_id

, last_name

, job_id

, salary

FROM employees

WHERE last_name = 'Austin' OR last_name = 'Chen';

 

-- emp

 

SELECT employee_id

, last_name

, job_id

, salary

FROM employees

-- WHERE salary >= 10000 AND salary <= 15000;

WHERE salary BETWEEN 10000 AND 15000;

 

-- emp last_name'Austin', 'Chen'인 사원의 정보를 얻어보자.

-- 출력 결과> 사번, last_name, job_id, salary

SELECT employee_id

, last_name

, job_id

, salary

FROM employees

-- WHERE last_name = 'Austin' OR last_name = 'Chen';

WHERE last_name IN('Austin', 'Chen');

 

-- emp에서 입사 일자가 97년인 사원의 정보를 얻어오자.

SELECT employee_id

, last_name

, hire_date

FROM employees

WHERE hire_date LIKE '97%';

 

-- emp에서 이름이 'Au' 사원의 정보를 얻어보자.

SELECT employee_id

, last_name

, hire_date

FROM employees

WHERE last_name LIKE 'A%';

 

-- emp 에서 모든 사원의 정보를 얻어보자.

-- , 월급순(내림차순)이다.

-- 출력결과 >사번, 이름(), 월급

SELECT employee_id, last_name, salary

FROM employees

ORDER BY salary ASC;

 

-- 전체 사원의 평균 월급

SELECT AVG(salary)

FROM employees;

 

--

 

SELECT AVG(salary)

FROM employees

WHERE salary>10000;

 

--

 

-- 부서번호가 50인 사원의 평균 월급을 구하라.

 

SELECT AVG(salary)

FROM employees

WHERE department_id = 50;

 

-- 각 부서의 평균 월급을 구하라.

-- 출력 결과 >부서번호, 평균 월급

SELECT department_id, AVG(salary)

FROM employees

GROUP BY department_id

ORDER BY AVG(salary) ASC;

 

--

 

SELECT TO_CHAR(hire_date, 'YYYY'), AVG(salary)

FROM employees

GROUP BY TO_CHAR(hire_date, 'YYYY')

HAVING AVG(salary) >= 10000;

 

-- 부서 번호가 30, 50이고 월급이 5000 이하인 사원의 정보를 구하자.

-- 출력결과 >사원번호, 이름(), 부서번호, 월급

SELECT employee_id, last_name, department_id, salary

FROM employees

WHERE (department_id = 30 OR department_id = 50) AND salary <= 5000;

 

-- 부서번호가 10 또는 20인 부서의 최대 월급을 구하자.

-- 출력결과 >부서번호, 최대월급

SELECT department_id, MAX(salary)

FROM employees

WHERE department_id IN (10, 20)

GROUP BY department_id;

 

-- 위와 똑같음

SELECT department_id, MAX(salary)

FROM employees

GROUP BY department_id

HAVING department_id IN (10, 20);

 

--

 

-- 직무 ID 별 최대 월급을 구하자. MAX(salary) 사용.

-- 출력 결과 >직무ID , 최대월급

SELECT job_id, MAX(salary)

FROM employees

GROUP BY job_id

ORDER BY job_id ASC;

 

-- 직무 ID'SA_REP' 거나 'SA_MAN' 이고,

-- 입사일자가 98년인 사원의 정보를 구하자.

-- 출력 결과 >사원번호, 이름(), 직무ID, 입사일자

SELECT employee_id, last_name, job_id, hire_date

FROM employees

WHERE (job_id = 'SA_REP' OR job_id = 'SA_MAN') AND --hire_date LIKE '98%';

-- TO_CHAR(hire_date, 'YYYY') = '1998';

EXTRACT (YEAR FROM hire_date) = '1998';

 

-- 단일 행 함수(문자, 숫자, 날짜, NULL, 변환, 기타)

SELECT CAST('22-OCT-1997' AS TIMESTAMP WITH LOCAL TIME ZONE)

FROM dual;

 

--

 

SELECT job_id,

CASE job_id

WHEN 'SA_MAN' THEN

'Sales Dept'

WHEN 'SA_REP' THEN

'Sales Dept'

ELSE

'Another'

END CASE

FROM jobs

WHERE job_id LIKE 'S%';

 

-- 사원번호가 150, 170인 사원의 정보를 얻어보자.

-- 출력결과 >사번, 이름, 월급, commission_pct, 매니저ID

SELECT employee_id, last_name, salary, commission_pct, manager_id

FROM employees

-- WHERE employee_id = 150 OR employee_id = 170;

WHERE employee_id IN(150, 170);

 

-- 사원의 월별 입사자 수를 얻어보자.

-- 출력결과> , 입사자 수

SELECT TO_CHAR(hire_date, 'mm') AS hd, count(*) -- 별칭(애칭)hd를 사용

FROM employees

GROUP BY TO_CHAR(hire_date, 'mm');

ORDER BY hd;

 

-- 주민등록번호 770525-1567423

-- 770525-1******으로 나타내 보자.

--SELECT RPAD('770525-1567423', 8, '*')

SELECT CONCAT(SUBSTR('770525-1567423', 1, 8), '******')

FROM DUAL;

 

--???

SELECT RPAD('770525-1567423', 20, '*')

FROM DUAL;

 

-- 각 사원의 월급 등급을 알아보자.

-- 출력 결과 >사원번호, 이름, 월급, 등급(10단계)

SELECT employee_id,

last_name,

salary,

WIDTH_BUCKET(salary, 2100, 24000, 10) AS GRADE

FROM employees

ORDER BY GRADE DESC;

 

-- NULL과의 연산

SELECT NULL + 10

FROM DUAL;

 

-- 직원들의 예상 월급을 구하라.

-- 출력결과>사번,이름,월급,commision_pct,예상월급

SELECT employee_id,

last_name,

salary,

salary + salary * commission_pct --NVL(TO_CHAR(commission_pct), 0) AS "commision"

FROM employees;

 

-- 분기별 입사 인원 수를 구하라.

-- 출력결과 >분기, 입사 인원 수

SELECT CEIL(EXTRACT (MONTH FROM hire_date)/3) AS quater,

, COUNT(*)

FROM employees

GROUP BY CEIL(EXTRACT (MONTH FROM hire_date)/3);

 

-- 사원의 근무기간을 구하라.

-- 출력결과 >사원번호, 이름, 입사일자, 근무기간(), 근무기간()

SELECT employee_id,

last_name,

hire_date,

FLOOR(months_between(SYSDATE, hire_date)/12) AS "근무기간()",

FLOOR(MOD(months_between(SYSDATE, hire_date), 12)) AS "근무기간()"

FROM employees;

 

 

SELECT ADD_MONTHS(SYSDATE, 12)

FROM dual;

 

--

 

SELECT --employee_id

CAST(employee_id AS CHAR(6))

FROM employees;

 

--

SELECT TO_CHAR(SYSDATE, 'YYY-MM-DD HH24:MI:SS')

FROM DUAL;

 

-- 오늘 + 1

SELECT SYSDATE + 365 AS PLUSDATA

FROM DUAL;

 

SELECT TO_DATE('2008-01-01') + 365 AS PLUSDATA

FROM DUAL;

 

-- 분기별 입사 인원수를 구하자.

-- 출력 결과 >분기, 입사인원

SELECT CEIL(EXTRACT(MONTH FROM hire_date)/3) AS quater,

COUNT(*)

FROM employees

GROUP BY CEIL(EXTRACT(MONTH FROM hire_date)/3)

ORDER BY quater;

 

-- TO_CHAR(hire_date)를 사용해서 위와 같은 결과 값 출력

SELECT TO_CHAR(hire_date, 'Q') AS quater

FROM employees

--GROUP BY TO_CHAR(hire_date, 'D')

ORDER BY quater;

 

-- job_id'SA_MAN'인 사원은 'Sales_Manager',

-- 'SA_REP'인 사원은 'Sales_Representative'

-- 기타 사원은 'Other'로 표시하여라(DECODE 사용)

-- 출력결과 >사번, 이름, job_id, job_id fullname

SELECT employee_id as "사번",

last_name as "이름",

job_id,

DECODE(job_id, 'SA_MAN', 'Sales_Manager', 'SA_REP', 'Sales_Representative', 'Other') AS AAA

FROM employees WHERE job_id LIKE 'S%'

ORDER BY job_id ASC;

 

-- 사원의 월급 랭크를 만들어 보자.

-- 5000미만이면 l, 5000이상이면 M, 10000이상이면 H

-- 출력 결과 >사원번호, 이름, 월급, 등급

SELECT employee_id,

last_name,

salary,

CASE employee_id

WHEN salary<5000 THEN 'L'

WHEN salary<10000 THEN 'M'

ELSE 'H'

END CASE

FROM employees;

 

-- 부서별 인원 수를 구해보자.

SELECT department_id, COUNT(*)

FROM employees

WHERE department_id IS NOT NULL

GROUP BY department_id;

 

SELECT job_id, SUM(salary)

FROM employees

GROUP BY job_id;

 

 

-- job_id별 최대 월급을 산출하라.

-- , 최대 월급이 10000 이상인 그룹만 표시하라.

SELECT DISTINCT JOB_ID

, MAX(salary) OVER(PARTITION BY JOB_ID ORDER BY JOB_ID DESC) as "Salary Over"

FROM employees;

 

-- INLINE VIEW (테이블 안에 테이블을 한번 더 정의. FROM 절 안에 쿼리가 포함되어 있는 형태)

SELECT *

FROM(

SELECT DISTINCT JOB_ID, MAX(salary) OVER(PARTITION BY JOB_ID ORDER BY job_id DESC) as mscx

FROM employees)

WHERE mscx >= 10000;

 

-- RANK(), ORDER BY 절이 항상 필요

SELECT employee_id

, salary

, RANK() OVER(PARTITION BY department_id ORDER BY salary DESC) as rnk

FROM employees; -- department_id 별로 묶어서 순위를 출력(PARTITION BY department_id)

 

 

-- 부서별 월급이 1~5등인 사원의 정보를 보자. INLINE VIEW로 작성.

-- , 사원이 5명 이상인 부서로 한한다.

-- 출력결과 >사번, 이름, 월급, 등급

SELECT *

FROM

(SELECT employee_id

, last_name

, salary

, RANK() OVER(PARTITION BY department_id ORDER BY salary DESC) as rnk --부서별로 등급이 어떻게 되는지?

, COUNT(*) OVER(PARTITION BY grade) as cnt --속한 부서의 인원이 몇 명인지?

FROM employees)

WHERE rnk <= 5 AND cnt >=5; -- 사원수(cnt)5명 이상, 부서별 월급이 1~5(rnk)

 

-- 각 사원의 월급 등급을 부서 평균과 비교하여 다음과 같이 등급을 정하자. 평균보다 작으면 L, 평균과 같으면 S, 크면 H

-- 출력결과 >사번, 이름, 월급, 등급

SELECT employee_id

, last_name

, salary

, RANK() OVER(PARTITION BY department_id ORDER BY salary DESC) as rnk

--, ROUND(AVG(salary) OVER (PARTITION BY department_id), 0) as avg

, CASE

WHEN salary <AVG(salary) OVER (PARTITION BY department_id) THEN

'L'

WHEN salary = AVG(salary) OVER (PARTITION BY department_id) THEN

'S'

WHEN salary >AVG(salary) OVER (PARTITION BY department_id) THEN

'H'

END as 등급

FROM employees;

 

-- NTILE

SELECT salary,

NTILE(10) OVER(ORDER BY salary ASC) as ntile

FROM employees;

 

-- 부서별로 입사 순위가 빠른 순서로 순위 1,2위를 얻어보자.

-- 출력결과> 부서번호, 이름, 사원번호, 순위

SELECT *

FROM(

SELECT department_id

, last_name

, employee_id

, RANK() OVER(PARTITION BY department_id ORDER BY hire_date DESC) as rnk

FROM employees)

where rnk IN(1,2);

 

-- job_id별로 월급이 낮은 20%의 사람의 정보를 얻어보자.

-- 출력결과> job_id, 사번, 이름, 월급, 등급(%)

SELECT *

FROM(

SELECT job_id

, employee_id

, last_name

, salary

, ROUND(PERCENT_RANK() OVER(ORDER BY salary DESC), 2) as RANK

FROM employees)

WHERE RANK <= 0.2;

 

 

-- ROW_NUMBER(), 1부터 10까지 출력(INLINE VIEW)

SELECT *

FROM(

SELECT employee_id

, department_id

, salary

, ROW_NUMBER() OVER(ORDER BY salary DESC) AS rn

FROM employees

WHERE department_id = 80)

WHERE rn BETWEEN 1 AND 10;

 

-- JOIN

SELECT employee_id

, department_id

FROM employees

WHERE department_id IN(80, 90);

 

SELECT department_id

, department_name

FROM departments

WHERE department_id IN(80, 90);

 

-- 비명시적 JOIN (하나의 쿼리문으로 두 개의 테이블에 있는 데이터를 한꺼번에 가져올 수 있다)

SELECT employee_id

, e.department_id

, department_name

FROM employees e, departments d

WHERE e.department_id = d.department_id -- employees에 있는 department_iddepartments에 있는 department_id를 연결한다.

AND e.department_id IN(80, 90);

 

-- 부서의 정보를 얻어보자

-- 출력결과> 부서번호, 부서이름, 부서위치(도시이름-LOCATIONS)

SELECT department_id

, department_name

, city

FROM departments d, locations l

WHERE d.location_id = l.location_id;

 

-- 명시적 JOIN

SELECT d.department_id

, d.department_name

, city

FROM departments d JOIN locations l

ON d.location_id = l.location_id; -- ONemployeesdepartmentJOIN하기 위한 조건을 정의한다.

 

-- 사원번호가 132, 150번인 사원에 대하여 월급 정보를 얻어보자.

-- 출력결과> 사번, 월급, 최소 월급, 최대 월급(JOBS)

SELECT employee_id

, salary

, j.min_salary

, j.max_salary

FROM employees e JOIN jobs j

ON employee_id IN(132,150)

WHERE e.job_id = j.job_id;

 

-- 사원번호(employees)164, 170인 사원의 job_title(jobs), department_name(departments)을 얻어보자.

-- 출력결과> 사번, job_title, department_name (비명시적)

SELECT employee_id

, job_title

, department_name

FROM employees e, jobs j, departments d

WHERE e.job_id = j.job_id AND e.department_id = d.department_id

AND employee_id IN(164,170);

 

 

-- 명시적 JOIN으로 바꿔서 출력

SELECT employee_id

, job_title

, department_name

FROM employees e JOIN jobs j

ON e.job_id = j.job_id

JOIN departments d

ON e.department_id = d.department_id

AND employee_id IN(164, 170);

 

 

-- OUTER JOIN(null 데이터 출력을 위한 JOIN)

-- 19991월부터 6월까지 입사한 인원의 정보를 얻어보자.

SELECT employee_id

, last_name

, hire_date

FROM employees

WHERE TO_CHAR(hire_date, 'YYYY-MM') BETWEEN '1999-01' AND '1999-06'

ORDER BY hire_date ASC;

 

-- 위 예제에 부서 이름 출력

SELECT employee_id

, last_name

, hire_date

, department_name

FROM employees e LEFT OUTER JOIN departments d

ON e.department_id = d.department_id

WHERE TO_CHAR(hire_date, 'YYYY-MM') BETWEEN '1999-01' AND '1999-06'

ORDER BY hire_date ASC;

 

-- 위 예제를 비명시적으로 바꿈

SELECT employee_id

, last_name

, hire_date

, department_name

FROM employees e, departments d

WHERE e.department_id = d.department_id(+) -- (+)를 추가

AND TO_CHAR(hire_date, 'YYYY-MM') BETWEEN '1999-01' AND '1999-06'

ORDER BY hire_date ASC;

 

 

-- 부서와 부서 관리자 정보를 얻어보자.

-- , 부서의 관리자가 없는 부서의 정보도 얻자. OUTER JOIN으로 해야함.

-- 출력결과> 부서이름, 부서관리자 아이디, 부서관리자 이름

SELECT department_name

, d.manager_id

, last_name

FROM employees e RIGHT OUTER JOIN departments d -- ON에서 지정한 컬럼 데이터에 NULL이 있는 쪽을 LEFT/RIGHT로 지정함.

ON e.employee_id = d.manager_id;

--ON e.manager_id = d.manager_id;

 

 

-- 비명시적

SELECT department_name

, d.manager_id

, last_name

FROM departments d, employees e

WHERE d.manager_id = e.employee_id(+);

 

-- 각 사원의 매니저 이름을 얻어보자. (SELF JOIN. 자기 자신을 JOIN)

-- 출력결과> 사원번호, 이름, 매니저의 사번, 매니저 이름

SELECT a1.employee_id

, a1.last_name

, a2.manager_id

, a2.last_name

FROM employees a1 RIGHT OUTER JOIN employees a2

ON a2.manager_id = a1.employee_id;

 

-- 사원(EMP), 부서(DEPT), 급여등급(SALGRADE)

-- 1. 사원 테이블에서 사원번호가 7369, 7698 번인 사원번호와 이름을 출력하세요?

SELECT empno

, ename

FROM emp

WHERE empno IN(7369, 7698);

 

-- 2. 사원 테이블에서 사원번호가 7369, 7698 번인 아닌 사원번호와 이름을 출력하세요?

SELECT empno

, ename

FROM emp

WHERE empno != 7369 AND empno != 7698;

 

-- 3. 사원 테이블에서 급여(SAL)3000에서 5000사이인 사원 정보를 다 출력하세요?

SELECT *

FROM emp

WHERE sal >= 3000 AND sal <= 5000;

 

-- 4. 사원 테이블에서 고용일자(HIREDATE)1981121일 이후 고용된 사원 정보를 다 출력하세요?

SELECT *

FROM emp

WHERE TO_CHAR(hiredate, 'YYYY-MM-DD') >= '1981-12-01'

ORDER BY hiredate ASC;

 

-- 5. 사원 테이블에서 직업(JOB)SALESMAN 중에서 사원번호의 최대값을 출력하세요?

SELECT MAX(empno), job

FROM emp

WHERE job = 'SALESMAN'

GROUP BY job;

 

-- 6. 사원 테이블에서 각 사원에 부서명을 아래 예제처럼 출력하세요

-- (사원, 부서 테이블 조인 시 부서가 없는 사원은 출력 안함)

-- ex) 정렬은 부서명(DNAME), 사원명(ENAME) 오름차순

SELECT dname

, empno

, ename

FROM emp e JOIN dept d

ON e.deptno = d.deptno

ORDER BY dname ASC;

-- 7. 사원 테이블에서 각 사원에 부서명을 아래 예제처럼 출력하세요

-- (사원, 부서 테이블 조인 시 부서가 없는 사원도 출력)

-- ex) 정렬은 부서명(DNAME), 사원명(ENAME) 오름차순

SELECT dname

, empno

, ename

FROM emp e LEFT OUTER JOIN dept d

ON e.deptno = d.deptno

ORDER BY dname ASC;

 

-- 8. 부서 위치가 'DALLAS', 'CHICAGO' 곳에 근무하는 사원 정보 아래

-- 예제처럼 출력하세요

-- ex) 정렬은 부서위치(LOC) 내림차순, 사원명(ENAME) 오름차순

SELECT loc

, empno

, ename

FROM emp e JOIN dept d

ON e.deptno = d.deptno

WHERE d.loc IN('DALLAS', 'CHICAGO')

ORDER BY LOC DESC;

-- 9. 부서별 최고 급여(SAL) 금액을 아래 예제처럼 출력하세요

-- ex) 부서 없는 사원은 제외

SELECT d.deptno

, MAX(sal)

FROM emp e JOIN dept d

ON e.deptno = d.deptno

GROUP BY d.deptno

ORDER BY deptno ASC;

-- 10. 부서별 최고 급여(SAL) 금액을 받는 사원 정보를 아래 예제처럼 출력하세요

-- ex) 부서 없는 사원은 제외

SELECT DISTINCT deptno

, MAX_SAL

, empno

, ename

, job

FROM emp,

(SELECT DISTINCT MAX(sal)

OVER(PARTITION BY deptno ORDER BY deptno ASC) AS MAX_SAL

FROM emp)

WHERE deptno IS NOT NULL AND MAX_SAL=sal

ORDER BY deptno;

-- 전체 사원에 대한 평균 월급을 구하자.

SELECT AVG(salary)

FROM employees;

-- 전체 사원 중에서 평균 월급보다 많이 받는 사원을 구하자. (서브쿼리)

SELECT employee_id

, last_name

, salary

FROM employees

WHERE salary >(SELECT AVG(salary)

FROM employees

);

 

-- 직무별 최대 급여를 받는 사원의 정보를 얻자.

-- 부서별 최대월급을 받는 사람이 한 명이 아니라, 복수의 사람이 출력되면 WHERE 절에서 서브쿼리를 작성해야 한다.

-- 출력결과 >사번, 이름, 월급

 

SELECT job_id

, MAX(salary)

FROM employees

GROUP BY job_id;

------------------------------ 일단 이 정도, 그 다음에

 

SELECT employee_id

, last_name

, salary

FROM employees

WHERE (job_id, salary) IN(SELECT job_id

, MAX(salary)

FROM employees

GROUP BY job_id

);

----------- 이렇게 서브쿼리를 작성해서, 직무별 최대 급여를 받는 사원의 정보를 얻었다.

 

 

-- 부서별로 입사일이 가장 오래된 사원의 정보를 얻자.

-- 출력결과 >사번, 이름, 부서, 입사일자

SELECT job_id

, MIN(hire_date)

FROM employees

GROUP BY job_id;

 

SELECT employee_id

, last_name

, department_id

, hire_date

FROM employees

WHERE (department_id, hire_date) IN(SELECT department_id

, MIN(hire_date)

FROM employees

GROUP BY department_id

);

 

-- 위 예제를 상관하위질의로 바꿔라.

SELECT employee_id

, last_name

, department_id

, hire_date

FROM employees e1

WHERE hire_date = (SELECT MIN(hire_date)

FROM employees e2

WHERE e2.department_id = e1.department_id

);

 

-- 위 예제를 JOIN으로 바꿔라.

SELECT employee_id

, last_name

, e.department_id

, hire_date

FROM employees e JOIN(SELECT department_id

, MIN(hire_date) as mnhrd

FROM employees

GROUP BY department_id

) d

ON e.department_id = d.department_id

WHERE e.hire_date = d.mnhrd;

 

 

-- JOIN

SELECT employee_id

, last_name

, e.job_id

, salary

FROM employees e JOIN(SELECT job_id

, MAX(salary) as mxsal

FROM employees

GROUP BY job_id

) v

ON e.job_id = v.job_id

WHERE e.salary = v.mxsal;

 

-- 상관하위질의

SELECT employee_id

, last_name

, job_id

, salary

FROM employees e1

WHERE salary = (SELECT MAX(salary)

FROM employees e2

WHERE e2.job_id = e1.job_id

);

 

 

-- 부서별 평균 급여보다 적게 받는 사원의 정보를 얻어보자.

-- 출력결과 >사번, 이름, 부서이름, 급여

-------------------------------------------------------------- JOIN으로 작성

SELECT employee_id

, last_name

, e.department_id

, salary

FROM employees e JOIN(SELECT department_id

, AVG(salary) as agsal

FROM employees

GROUP BY department_id

) v

ON e.department_id = v.department_id

JOIN departments d

ON e.department_id = d.department_id

WHERE e.salary <v.agsal;


-------------------------------------------------------------- 상관하위질의

SELECT employee_id

, last_name

, department_id

, salary

FROM employees e1

WHERE salary <(SELECT AVG(salary) as agsal

FROM employees e2

WHERE e1.department_id = e2.department_id

);

--------------------------------------------------------------

 

-- JOIN

SELECT employee_id

, last_name

, e.job_id

, salary

FROM employees e JOIN(SELECT job_id

, MAX(salary) as mxsal

FROM employees

GROUP BY job_id

) v

ON e.job_id = v.job_id

WHERE e.salary = v.mxsal;

 

 

SELECT employee_id

, last_name

, job_id

, salary

FROM employees e1

WHERE salary = (SELECT MAX(salary)

FROM employees e2

WHERE e2.job_id = e1.job_id

);

-- SEQUENCE

INSERT INTO dept(deptno

, dname)

VALUES(dept_id_seq.NEXTVAL

, 'CHA')

 

--

 

CREATE SEQUENCE dept_id_seq

START WITH 50

INCREMENT BY 10

MAXVALUE 999;

 

 

-- 1. 사원 테이블에서 각 사원에 급여(SAL) 등급을 아래 예제처럼 출력하세요.

SELECT empno

, ename

, sal

, grade

FROM emp e JOIN salgrade s

ON e.sal <s.hisal AND e.sal >s.losal

ORDER BY grade ASC;

 

-- 2. 사원 테이블에서 평균 급여(SAL) 보다 높은 사원 정보를 아래 예제처럼 출력하세요.

SELECT empno

, ename

, job

, sal

FROM emp

WHERE sal >(SELECT AVG(sal)

FROM emp

)

ORDER BY sal DESC;

 

-- 3. 사원 테이블에서 부서별 평균 급여(SAL) 보다 높은 사원 정보를 아래 예제처럼 출력하세요.

-- 정렬은 급여 내림차순

SELECT dname

, empno

, ename

, job

, sal

FROM emp e JOIN(SELECT deptno

, AVG(sal) as agsal

FROM emp

GROUP BY deptno

) v

ON e.deptno = v.deptno

JOIN dept d

ON e.deptno = d.deptno

WHERE e.sal >v.agsal

ORDER BY sal DESC;

 

-- 4. 사원 테이블에서 각 사원에 급여(SAL) 순위 점수 별로 인원수를 아래 예제처럼 출력하세요.

-- 급여순위점수(SALGRADE) 테이블 JOIN

SELECT DISTINCT grade
, losal
, hisal
, COUNT(*) OVER(PARTITION BY grade) as cnt
FROM emp e JOIN salgrade s
ON e.sal >s.losal AND e.sal <s.hisal
ORDER BY grade ASC;

 

-- 5.부서명이 'RESEARCH' 이거나 부서위치가 'NEW YORK' 사원 정보를 아래 예제처럼 출력하세요

SELECT dname

, loc

, empno

, ename

FROM emp e JOIN dept d

ON e.deptno = d.deptno

WHERE dname = 'RESEARCH' OR loc = 'NEW YORK'

ORDER BY dname ASC;

 

-- 6.사원 테이블에서 EMPNO, MGR, SAL 세 개의 컬럼을 단순 숫자 의미로 가정 할 경우 세 개의 값 중 최대값(MAX_VALUE), 최소값(MIN_VALUE) 을 아래 예제처럼 출력하세요

-- ex) EMPNO, MGR, SAL 컬럼 중 널 값이 존재할 경우 0으로 치환

-- 정렬은 최대값 내림차순

SELECT empno
, mgr
, sal
, GREATEST(TO_NUMBER(NVL(EMPNO,0))
, TO_NUMBER(NVL(MGR,0))
, TO_NUMBER(NVL(SAL,0))) MAX_VALUE
, LEAST(TO_NUMBER(NVL(EMPNO,0)),TO_NUMBER(NVL(MGR,0)),TO_NUMBER(NVL(SAL,0))) MIN_VALUE
FROM emp
ORDER BY 4 DESC;

-- 7.부서 테이블에서 DNAME 컬럼의 길이가 6자리 이상이면은 5자리까지 데이터만 보여주고 ‘..’ 뒤에 붙여준다. 아래 예제처럼 출력하세요

SELECT dname

, CONCAT(SUBSTR(dname, 1, 5), '..')

FROM dept;

 

 

-- 8.사원 테이블에서 고용일자(HIREDATE) 해당 년 월의 마지막 날짜(HIREDATE_MONTH_LASTDAY), 고용일자부터 2006/08/05

-- 일자까지 근무일(WORK_DAY)을 아래 예제처럼 출력하세요

SELECT empno

, hiredate

, LAST_DAY(hiredate)

, TO_DATE('2006/08/05','YYYY/MM/DD') - hiredate WORK_DAY

FROM emp;