참고
JOIN
NOTE
SQL에서의 2개 이상의 테이블에서 행을 결합하여 결과를 생성할 때 사용하는 방법입니다.
Join의 종류
•
Join을 사용할 때 ON, WHERE과 같이 조건을 지정하지 않으면 매우 많은 결과를 생성할 수 있습니다.
•
Join은 종종 중복된 컬럼 이름을 포함할 수 있으므로 주의해서 사용해야 합니다.
CREATE TABLE Department
(
DeptID INT NOT NULL PRIMARY KEY COMMENT '부서 ID',
DeptName VARCHAR(100) NOT NULL COMMENT '부서 이름',
ParentDeptID INT NULL COMMENT '상위 부서 ID' -- 상위 부서를 가리키는 외래키
) COMMENT '부서 정보';
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
Name VARCHAR(100),
Email VARCHAR(100),
Salary DECIMAL(10, 2),
DeptID INT,
FOREIGN KEY (DeptID) REFERENCES Department(DeptID)
);
SQL
복사
공통 DDL
INNER JOIN(내부 조인)
NOTE
INNER JOIN은 두 테이블간의 교집합을 반환합니다. 즉 양쪽 테이블 모두에서 일치하는 행만 결과에 포함됩니다.
교집합
SELECT <열 목록>
FROM <첫 번째 테이블>
INNER JOIN <두 번째 테이블>
ON <조인 조건>
[WHERE 검색 조건]
#INNER JOIN을 JOIN이라고만 써도 INNER JOIN으로 인식합니다.
SQL
복사
SELECT
Employees.Name AS EmployeeName,
Department.DeptName AS Department
FROM
Employees
INNER JOIN
Department
ON
Employees.DeptID = Department.DeptID;
SQL
복사
DCL
OUTER JOIN(외부 조인)
NOTE
OUTER JOIN은 일치하는 행 뿐만 아니라, 한 쪽 테이블에는 일치하는 행이 없더라도 다른 한 쪽 테이블의 행을 포함하여 결과를 반환합니다.
SELECT <열 목록>
FROM <첫 번째 테이블(LEFT 테이블)>
<LEFT | RIGHT | FULL> OUTER JOIN <두 번째 테이블(RIGHT 테이블)>
ON <조인 조건>
[WHERE 검색 조건]
SQL
복사
•
FULL OUTER JOIN의 경우 MySQL에서 지원하지 않습니다.
SELECT E.Name AS EmployeeName,
D.DeptName AS Department
FROM Department D
LEFT OUTER JOIN Employees E on E.DeptID = D.DeptID
SQL
복사
DCL
SELECT E.Name AS EmployeeName,
D.DeptName AS Department
FROM Department D
RIGHT OUTER JOIN Employees E on E.DeptID = D.DeptID;
SQL
복사
DCL
CROSS JOIN
NOTE
CROSS JOIN은 두 테이블 간의 가능한 모든 조합을 생성합니다. 이 유형의 JOIN은 특별한 JOIN 조건 없이 두 테이블의 모든 행이 서로 조합됩니다.
SELECT *
FROM <첫 번째 테이블>
CROSS JOIN <두 번째 테이블>
SQL
복사
SELECT
E.Name AS Employee,
D.DeptName AS Department
FROM
Employees E
CROSS JOIN
Department D;
SQL
복사
SELF JOIN
NOTE
SELF JOIN은 테이블이 자기 자신과 조인되는 것을 말합니다. 주로 순환관계를 조회할때 사용합니다.
SELECT <열 목록>
FROM <테이블> 별칭A
INNER JOIN <테이블> 별칭B
[WHERE 검색 조건]
SQL
복사
SELF JOIN 예약어가 있는게 아닌 FROM과 동일한 테이블을 사용하는 경우를 말합니다.
SELECT
child.DeptName ,
parent.DeptName
FROM
Department AS child
LEFT JOIN
Department AS parent ON child.ParentDeptID = parent.DeptID
SQL
복사
UNION
NOTE
UNION은 여러 개의 SELECT문 결과를 하나의 테이블이나 결과 집합으로 표현할 때 사용합니다. 단 각각의 SELECT에서 선택된 필드의 개수, 타입, 순서가 모두 같아야합니다.
SELECT 필드이름 FROM 테이블이름
UNION
SELECT 필드이름 FROM 테이블이름
SQL
복사
SUBQUERY(서브쿼리)
NOTE
서브쿼리란 다른 쿼리 내부에 포함되어 있는 SELECT문을 의미한다.
-- 스칼라 서브쿼리(Scalar Sub Query): 하나의 컬럼처럼 사용 (표현 용도)
SELECT col1, (SELECT ...)
-- 인라인 뷰(Inline View): 하나의 테이블처럼 사용 (테이블 대체 용도)
FROM (SELECT ...)
-- 일반 서브쿼리: 하나의 변수(상수)처럼 사용 (서브쿼리의 결과에 따라 달라지는 조건절)
WHERE col = (SELECT ...)
SQL
복사
서브쿼리 명칭
•
서브쿼리는 중첩이 가능하며 SELECT, FROM, WHERE이외의 위치에서도 사용이 가능하다.
◦
SELECT
◦
FROM
◦
WHERE
◦
HAVING
◦
ORDER BY
◦
INSERT VALUES 부분대체
◦
UPDATE SET 부분대체
서브쿼리가 먼저 실행되고 메인 쿼리가 실행됩니다. (메인쿼리를 서브쿼리 컬럼에서 사용불가능)
SELECT
E.Name,
E.Email,
(SELECT DeptName FROM Department WHERE DeptID = E.DeptID) AS DeptName
FROM
Employees E;
SQL
복사
Select 위치에서 사용
SELECT DeptName, AvgSalary
FROM
(SELECT D.DeptName, AVG(E.Salary) AS AvgSalary
FROM Employees E
JOIN Department D on E.DeptID = D.DeptID
GROUP BY D.DeptName) AS DeptAvgSalaries;
SQL
복사
FROM 위치에서 사용
SELECT Name, Email
FROM Employees
WHERE DeptID = (SELECT DeptID FROM Department WHERE DeptName='IT')
SQL
복사
WHERE 위치에서 사용
SUBQUERY 종류 - Nested Subquery(단일행)
NOTE
-- 부서가 ‘seattle’(대소문자 구분X)에 있는 부서의 부서 번호, 부서 이름.
-- 단일행
select department_id, department_name
from departments
where location_id = (select location_id
from locations
where upper(city) = upper('seattle'));
-- 전체 사원의 평균 급여보다 많이 받는 사원의 사번, 이름, 급여.
-- 급여순 정렬
select employee_id, first_name, salary
from employees
where salary > (select avg(salary)
from employees
)
order by salary desc;
-- ‘adam’과 같은 부서에 근무하는 사원의 사번, 이름, 부서번호.
select employee_id, first_name, department_id
from employees
where department_id = (select department_id from employees where first_name = 'adam');
SQL
복사
SUBQUERY 종류 - Nested Subquery(다중행)
NOTE
-- 근무 도시가 ‘seattle’(대소문자 구분X)인 사원의 사번, 이름.
-- 다중행 (in)
select employee_id, first_name, department_id
from employees
where department_id in (
select department_id
from departments
where location_id = (
select location_id
from locations
where city = 'seattle'
)
);
-- 다중열
-- 커미션을 받는 사원중 매니저 사번이 148인 사원의 급여와 부서번호가 일치하는 사원의 사번, 이름
select employee_id, first_name
from employees
where( salary, department_id ) in (
select salary, department_id
from employees
where commission_pct is not null
and manager_id = 148
);
-- 모든 사원 중 적어도(최소급여자보다) 30번 부서에서 근무하는 사원의 급여보다 많이 받는 사원의 사번, 이름, 급여, 부서번호
-- 다중행 (any)
select employee_id, first_name, department_id
from employees
where salary > any(
select salary
from employees
where department_id = 30
);
-- 30번 부서에서 근무하는 모든(최대급여자보다) 사원들보다 급여를 많이 받는 사원의 사번, 이름, 급여, 부서번호.
-- 다중행 (all)
select employee_id, first_name, department_id
from employees
where salary > all(
select salary
from employees
where department_id = 30
);
SQL
복사