SQL
-- SQL 4일차(join, subquery)
/*
join : N개 이상의 테이블을 서로 묶어서 하나의 결과집합을 만들어 내는 것
-- 관계형 데이터베이스의 가장 큰 특징
-- 테이블의 관계(1:1, 1:N)
ANSI 표준 구문
SELECT
FROM TABLE01 -- 테이블 여러개를 열거하면 안됨!! from 절에는 무조건 테이블 하나만 가능
[INNER] JOIN TABLE02 ON(조건) -- 조건이라는 건 연산자를 사용할 수 있다
[INNER] JOIN TABLE02 USING(컬럼명) -- 부모의 기본키와 자식의 외래키 컬럼명이 동일해야함.
NATURAL [INNER] JOIN TABLE02 -- 알 필요 X
LEFT|RIGHT|FULL [OUTER] JOIN TABLE02 ON(조건)
LEFT|RIGHT|FULL [OUTER] JOIN TABLE02 USING(컬럼명)
-- 마리아db는 full outer join을 지원하지 않음
-- 조건에 만족하지 않는 데이터까지 포함하여 join을 사용하는게 outer join. 누락된 데이터까지 포함하는 결과를 보고 싶을 때 사용.
CROSS JOIN TABLE02 -- 알 필요 X
*/
USE encore;
SELECT *
FROM department;
SELECT *
FROM employee;
SELECT d.dept_name,
e.emp_name
FROM department d, employee e; -- join시 조건을 걸어주지 않으면 1:N관계로 매핑해서 7 * 22 = 154개의 레코드가 생성된다
SELECT d.dept_name,
d.dept_id,
e.emp_name
FROM department d, employee e
WHERE d.DEPT_ID = e.DEPT_ID;
SELECT emp_name,
dept_name,
loc_describe
FROM employee e
INNER JOIN department d USING(dept_id) -- USING(d.dept_id) 처럼 USING 구문에 특정 테이블의 별칭을 사용하는 것은 불가능하다.
INNER JOIN location l ON(location_id = loc_id) -- ON(l.location_id = d.loc_id) 처럼 ON 구문에서는 테이블의 별칭을 사용할 수 있다.
WHERE dept_name LIKE '해외%'
ORDER BY 3, 1;
USE sqldb;
SELECT *
FROM usertbl;
SELECT *
FROM buytbl;
-- 사용자가 JYP인 유저의 이름과 구매상품을 조회한다면?
SELECT NAME,
prodName
FROM usertbl u
INNER JOIN buytbl b USING(userID)
WHERE userID = 'JYP';
SELECT NAME,
prodName
FROM usertbl u
INNER JOIN buytbl b ON(u.userID = b.userID)
WHERE u.userID = 'JYP'; -- 테이블 별칭을 붙여줘야함
-- 사용자의 아이디, 이름, 구매상품, 주소, 연락처를 조회하고 싶다면?
SELECT u.userID,
NAME,
prodName,
addr,
CONCAT(mobile1, mobile2) AS mobile
FROM usertbl u
JOIN buytbl b ON(u.userID = b.userID);
-- 위 요구사항에서 구매이력이 있는 회원만 조회한다면?
SELECT distinct u.userID, NAME, addr, CONCAT(mobile1, mobile2) AS mobile
FROM usertbl u
JOIN buytbl b ON(u.userID = b.userID);
SELECT u.userID, NAME, addr, CONCAT(mobile1, mobile2) AS mobile
FROM usertbl u
WHERE EXISTS (SELECT *
FROM buytbl b
WHERE u.userid = b.userid); -- 유무만 판별하고 데이터 내용은 중요하지 않은 키워드 exists
USE encore;
SELECT *
FROM sal_grade;
-- 업무적인 연관성이 없는 테이블도 조인이 가능하다. (ON() 구문을 이용한 조인)
SELECT emp_name,
salary,
slevel
FROM employee e
JOIN sal_grade s ON(e.salary BETWEEN s.lowest AND s.highest)
ORDER BY 3;
-- outer join : join의 조건에 만족하지 않는 모든 행을 조회할 때
SELECT emp_name,
dept_name
FROM employee e
RIGHT JOIN department d USING(dept_id); -- left: join이라는 키워드를 기준으로 join의 왼쪽에 있는건 left, 오른쪽에 있는 건 right.
-- left에 있는 모든 키워드를 반환한다. 즉 employee 테이블에 있는 모든 컬럼 출력.
USE sqldb;
-- 구매이력이 없는 사용자만 조회?
SELECT u.userid,
u.name,
b.prodname,
u.addr
FROM usertbl u
left JOIN buytbl b ON(u.userid = b.userid)
WHERE prodname IS NULL;
USE encore;
-- 부서배치를 받지 않은 사원의 이름, 부서명을 조회한다면?
SELECT emp_name,
dept_name
FROM employee e
LEFT JOIN department d USING(dept_id)
WHERE dept_name IS null;
-- 사원테이블에서 사원의 이름과 사수의 이름을 조회하고 싶다면? self join
SELECT e.emp_name,
m.emp_name AS mgr_name,
s.emp_name AS spr_name
FROM employee e
LEFT JOIN employee m ON(e.mgr_id = m.emp_id)
LEFT JOIN employee s ON(m.mgr_id = s.emp_id);
-- 서브쿼리 : 하나의 쿼리가 다른 쿼리에 포함되는 구조
-- 유형 : 단일행 서브쿼리(리턴dl 1건)(단일 열, 다중 열), 다중행 서브쿼리(리턴이 여러건)(단일 열, 다중 열)
-- 유형에 따라서 사용할 수 있는 연산자가 다르다
-- select절(scalar subquery), from절(inline view), where절(subquery)
-- 나승원 사원과 같은 부서원을 조회한다면?
SELECT dept_id
FROM employee
WHERE emp_name = '나승원';
SELECT *
FROM employee
WHERE dept_id = '50';
SELECT * -- mainquery
FROM employee
WHERE dept_id = (SELECT dept_id
FROM employee
WHERE emp_name = '나승원'); -- subquery
-- 나승원 사원과 같은 직급이고 나승원 사원보다 많은 급여를 받는 사원의 정보를 조회
SELECT *
FROM employee
WHERE job_id = ( SELECT job_id
FROM employee
WHERE emp_name = '나승원') && salary > (SELECT salary
FROM employee
WHERE emp_name = '나승원');
-- 부서별 급여총합이 가장 많은 부서의 부서명, 급여총합을 조회
SELECT d.dept_name,
max(sum(salary))
FROM employee e
JOIN department d USING(dept_id)
WHERE MAX(SUM(salary)) = (SELECT MAX(SUM(salary)) -- error. 집계함수가 집계함수를 중첩할 수 없다
FROM employee
GROUP BY dept_id);
SELECT e.dept_id,
MAX(total)
FROM (SELECT dept_id,
SUM(salary) AS 'total'
FROM employee
GROUP BY dept_id) v -- inline view
JOIN employee e ON(e.dept_id = v.dept_id);
SELECT d.dept_name,
MAX(total)
FROM (SELECT dept_id,
SUM(salary) AS 'total'
FROM employee
GROUP BY dept_id) v -- inline view
JOIN employee e ON(e.dept_id = v.dept_id)
JOIN department d ON(d.dept_id = e.dept_id);
-- 부서별 최소 급여를 확인하고 싶다면?
SELECT MIN(salary)
FROM employee e
GROUP BY dept_id;
SELECT *
FROM employee
WHERE (dept_id, salary) IN (SELECT dept_id,
MIN(salary)
FROM employee e
GROUP BY dept_id);
-- 과장직급의 급여를 확인한다면?
SELECT salary
FROM employee e
JOIN job j ON(e.job_id = j.job_id)
WHERE job_title = '과장';
SELECT salary
FROM employee e
JOIN job j ON(e.job_id = j.job_id)
WHERE job_title = '대리';
-- 과장직급보다 많은 급여를 받는 대리사원의 정보를 조회한다면?
-- > ANY : 비교대상 중 최솟값보다 큰 것
-- < ANY : 비교대상 중 최댓값보다 작은 것
-- > ALL : 비교대상 중 최댓값보다 큰 것
-- < ALL : 비교대상 중 최솟값보다 작은 것
SELECT emp_name,
salary
FROM employee e
JOIN job j ON(e.job_id = j.job_id)
WHERE job_title = '대리' && salary > ALL (SELECT salary
FROM employee e
JOIN job j ON(e.job_id = j.job_id)
WHERE job_title = '과장');
'한화시스템 BEYOND SW캠프 > TIL' 카테고리의 다른 글
[2주차] 24.01.18 목요일 (0) | 2024.01.18 |
---|---|
[2주차] 24.01.17 수요일 (0) | 2024.01.17 |
[2주차] 24.01.15 월요일 (1) | 2024.01.15 |
[1주차] 24.01.12 금요일 (1) | 2024.01.12 |
[1주차] 24.01.11 목요일 (0) | 2024.01.11 |