AS
- AS문은 컬럼이나 결과에 별칭(alias)을 부여한다.
SELECT column AS new_name FROM table
SELECT SUM(column) AS new_name FROM table
→ 컬럼명이 new_name으로 출력된다
- 별칭을 컬럼 명 다음에 쓰면 AS를 생략할 수 있다. 가독성이 나빠질 수 있으므로 주의해야 한다.
SELECT column1 alias1, column2 alias2 FROM table;
- AS연산자는 쿼리의 맨 마지막에 실행되기 때문에
WHERE
, GROUP BY
, HAVING
등에서 별칭을 쓸 수 없다.
- 정상 쿼리
SELECT customer_id, sum(amount) as total_spent FROM payment GROUP BY customer_id HAVING sum(amount) > 100
- 실행되지 않는 쿼리, 컬럼이 없다고 뜨면서 실행되지 않는다.
SELECT customer_id, sum(amount) as total_spent FROM payment GROUP BY customer_id HAVING total_spent > 100
- 정상 쿼리
SELECT customer_id, amount as new_name FROM payment WHERE amount > 2
- 실행되지 않는 쿼리
SELECT customer_id, amount as new_name from payment where new_name > 2
WHERE
절에서도 별칭을 사용하려면 서브쿼리나 HAVING절을 이용하면 된다.
SELECT *
FROM (
SELECT column_name AS alias_name
FROM table_name
) AS subquery
WHERE alias_name = 'value';
SELECT column_name AS alias_name
FROM table_name
HAVING alias_name = 'value';
JOIN
- 여러 테이블의 레코드를 결합하여 하나의 열로 표현하는 것 이다.
- 하나의 쿼리에서 연달아 여러 개의 JOIN을 적용할 수 있다.
FROM
절에 2개 이상의 테이블이 열거되고, 열거된 테이블 사이에 조인 방식을 기술한다.
ON
또는 WHERE
절에는 각 테이블의 레코드들 간의 연관성을 기술한다.
- 일반적으로 조인에서는 기본키(PK)와 외래키(FK)를 사용하여 연관성을 표현한다.
- 결합된 테이블 중 하나에만 존재하는 정보를 처리하는 방식에 따라 분류한다.
ANSI
표준 SQL은 다음 다섯 가지 유형(types)의 JOIN
을 규정하고 있다.
INNER
FULL OUTER
LEFT OUTER
RIGHT OUTER
CROSS
OUTER
를 쓰지 않고 JOIN
만 쓰면 내부(INNER) 조인이라고 간주한다.
JOIN
연산에 대한 조건문(condition)은 다음과 같다.
예제 테이블, 이름은 모두 고유한 이름이라고 가정.
Registrations | |
---|
reg_id | name |
1 | Andrew |
2 | Bob |
3 | Charlie |
4 | David |
Logins | |
---|
log_id | name |
1 | Xavier |
2 | Andrew |
3 | Yolanda |
4 | Bob |
NATURAL JOIN(자연 조인)
- 자연 조인은 두 개 이상의 테이블 간에
공통된 열 이름
을 기반으로 자동으로 조인하는 방식이다.
- 조인 대상 테이블들이
같은 이름의 컬럼
을 갖고 있다면 이 컬럼에 해당하는 값이 같은 레코드 쌍을 자동으로 결합하기 때문에 조인 조건을 별도로 기술하지 않아도 자연 조인 연산이 가능하다.
- 그러나 조건을 좀 더 명확하게 하기 위해
ON
, WHERE
, USING
등을 활용할 수도 있다.
- 자연 조인(
NATURAL
)은 조인의 유형이 아니라 조건이기 때문에 내부(INNER
)조인과 외부(OUTER
)조인 모두에 활용할 수 있다.
SELECT t1.col1, t1.col2, t2.col1, t2.col2
FROM table1 AS t1 NATURAL JOIN table2 AS t2;
SELECT A.학생이름, A.나이, B.학과이름, B.이수학점
FROM 학생 A NATURAL JOIN 전공 B
INNER JOIN(내부 조인)
- 두 테이블 모두에서 일치하는 레코드를 조회하는 조인이다.
- 대칭적이기 때문에 테이블 순서를 바꿔도 결과는 같다.
SELECT *
FROM TableA INNER JOIN TableB
ON TableA.col_match = TableB.col_match;
SELECT *
FROM TableB INNER JOIN TableA
ON TableB.col_match = TableA.col_match;
- PostgreSQL에서는 쿼리문에 그냥
JOIN
이라고 쓰면 INNER JOIN
으로 인식한다.
- 일반적으로
ON
절에서는 조인 조건을 기술하고 WHERE
절은 조건에 맞는 레코드만 선택하기 사용된다.
Oracle
의 내부 조인 구문 형식은 다음과 같다. 이 문법은 SQL 표준은 아니지만 대부분의 RDBMS에서 지원한다.
SELECT *
FROM TABLE_A A, TABLE_B B
WHERE A.COLUMN = B.COLUMN;
SELECT *
FROM Registrations INNER JOIN Logins
ON Registrations.name = Logins.name;
reg_id name log_id name
1 Andrew 2 Andrew
3 Bob 4 Bob
SELECT payment_id, payment.customer_id, first_name
FROM payment INNER JOIN customer
ON payment.customer_id = customer.customer_id
SELECT 학생.*, 계좌.*
FROM 학생 INNER JOIN 계좌
ON 학생.학생번호 = 계좌.학생번호
WHERE 학생.나이 >= 30
SELECT 학생.학생이름, 계좌.잔액
FROM 학생, 계좌
WHERE 학생.나이 >= 30 AND 학생.학생번호 = 계좌.학생번호;
OUTER JOIN(외부 조인)
- 외부 조인은 두 개 이상의 테이블 간에서 특정 조건을 기준으로 행을 매칭하여 조인하는 것을 의미한다.
- 외부 조인은 내부 조인과 동일하게 조건에 맞는 레코드를 결합시키면서도 조건에 맞지 않는 레코드도 결과에 포함시킬 수 있다.
JOIN
절을 기준으로 조건 불일치 레코드를 결과에 포함시키는 주체가 되는 테이블의 위치에 따라 세 가지 종류로 구분된다.
- 완전 외부 조인(Full Outer Join): 양쪽 테이블의 모든 행을 포함하고, 양쪽 테이블 중 어느 한쪽에 매칭되는 행이 있으면 매칭 결과를 반환하고, 양쪽 테이블 모두에 매칭되는 행이 없으면 NULL 값을 반환한다.
- 왼쪽 외부 조인(Left Outer Join): 왼쪽 테이블의 모든 행을 포함하고, 오른쪽 테이블과 매칭되는 행이 있으면 매칭 결과를 반환하고, 매칭되는 행이 없으면 NULL 값을 반환한다.
- 오른쪽 외부 조인(Right Outer Join): 오른쪽 테이블의 모든 행을 포함하고, 왼쪽 테이블과 매칭되는 행이 있으면 매칭 결과를 반환하고, 매칭되는 행이 없으면 NULL 값을 반환한다.
FULL OUTER JOIN(완전 외부 조인)
- 테이블A와 B의 가능한 모든 레코드를 조합한다.
- 서로 일치하는 데이터가 없으면 null로 표시된다.
- 대칭적이기 때문에 테이블 순서를 바꿔도 결과는 같다.
MySQL
은 완전 외부 조인을 지원하지 않는다. 대신 UNION ALL
연산을 사용할 수 있다.
SELECT *
FROM TableA FULL OUTER JOIN TableB
ON TableA.col_match = TableB.col_match;
SELECT * FROM Registrations
FULL OUTER JOIN Logins
ON Registrations.name = Logins.name;
reg_id name log_id name
1 Andrew 2 Andrew
2 Bob 4 Bob
3 Charlie null null
4 David null null
null null 1 Xavier
null null 3 Yolanda
SELECT employee_id, employee_name FROM employees
UNION ALL
SELECT customer_id, customer_name FROM customers;
- FULL OUTER JOIN에
WHERE A.key IS NULL OR B.key IS NULL
조건을 활용하여 양쪽 테이블에서 고유한 값을 조회할 수 있다.
- 대칭적이기 때문에 테이블 순서를 바꿔도 결과는 같다.
- INNER JOIN의 정반대인 결과가 나온다.
SELECT *
FROM TableA FULL OUTER JOIN TableB
ON TableA.col_match = TableB.col_match
WHERE TableA.id IS NULL OR TableB.id IS NULL
SELECT *
FROM Registrations FULL OUTER JOIN Logins
ON Registrations.name = Logins.name
WHERE Registrations.reg_id IS NULL OR Logins.log_id IS NULL
reg_id name log_id name
3 Charlie null null
4 David null null
null null 1 Xavier
null null 3 Yolanda
LEFT OUTER JOIN (LEFT JOIN)
- 왼쪽 테이블에 있는 레코드 세트를 출력하고 오른쪽 테이블에 일치하는 데이터가 없으면 null로 출력한다.
- 벤 다이어그램으로 보듯이 대칭적이지 않다. 따라서 테이블 순서가 중요하다.
SELECT *
FROM TableA LEFT OUTER JOIN TableB
ON TableA.col_match = TableB.col_match;
SELECT * FROM Registrations
LEFT OUTER JOIN Logins
ON Registrations.name = Logins.name
reg_id name log_id name
1 Andrew 2 Andrew
2 Bob 4 Bob
3 Charlie null null
4 David null null
SELECT A.학생이름, A.나이, B.과목코드, B.신청시각
FROM 학생 A LEFT OUTER JOIN 수강 B
ON A.학생번호 = B.학생번호
ORDER BY 과목코드 ASC
- 테이블A에만 있고 B에는 없는 행을 구하기 위해 LEFT OUTER JOIN을 이용하면서
WHERE B.key IS NULL
조건을 활용하는 방법이다.
- 대칭적이지 않기 때문에 테이블 순서가 중요하다.
SELECT *
FROM TableA LEFT OUTER JOIN TableB
ON TableA.col_match = TableB.col_match
WHERE TableB.id IS NULL
SELECT * FROM Registrations
LEFT OUTER JOIN Logins
ON Registrations.name = Logins.name
WHERE Logins.log_id IS NULL
reg_id name log_id name
3 Charlie null null
4 David null null
RIGHT OUTER JOIN (RIGHT JOIN)
- LEFT OUTER JOIN과 같은 방식으로 조인한다. 조인하는 테이블의 순서만 다르다.
SELECT * FROM TableA RIGHT OUTER JOIN TableB ON TableA.col_match = TableB.col_match;
- 테이블B에만 있는 데이터를 조회하기 위해 LEFT OUTER JOIN과 마찬가지로
WHERE A.key IS NULL
조건을 활용할 수 있다.
SELECT * FROM TableA RIGHT OUTER JOIN TableB ON TableA.col_match = TableB.col_match WHERE TableA.id IS NULL;
SELF JOIN(셀프 조인)
- 셀프 조인은 동일한 테이블에서의 조인이다. 컬럼을 구별하기 위해 테이블에 서로 다른 별칭을 사용해야 한다.
- 셀프 조인을 위한
SELF JOIN
이라는 예약어는 없으며 동일한 테이블에서 조인하면 셀프 조인이 된다.
- 조인 수행 방식에 따라
INNER
또는 OUTER
를 쓸 수 있다.
SELECT tableA.col, tableB.col
FROM table AS tableA JOIN table AS tableB
ON tableA.som_col = tableB.other_col
SELECT f1.title, f2.title, f1.length
FROM film AS f1
INNER JOIN film AS f2
ON f1.film_id != f2.film_id AND f1.length = f2.length
SELECT B.과목명, B.과목코드, A.과목명 AS 선수과목명, A.과목코드 AS 선수과목코드
FROM 과목 A RIGHT OUTER JOIN 과목 B
ON A.과목코드 = B.선수과목
CROSS JOIN(크로스 조인)
- 크로스 조인이란 조인하는 테이블의 레코드를 결합하는 조건 없이 가능한 모든 조합으로 결합하는 것이다.
- 관계 대수의
카티션 프로덕트(Cartesian Product)
연산과 같다.
WHERE
절로 결합 조건을 지정할 수도 있다.
SELECT column1, column2
FROM table1
CROSS JOIN table2
WHERE condition
SELECT 학생.*, 계좌.*
FROM 학생 CROSS JOIN 계좌
WHERE 학생.나이 >= 30
JOIN 연습문제
- 캘리포니아에 살고 있는 고객의 이메일 찾기
SELECT district, email
FROM address INNER JOIN customer
ON address.address_id = customer.address_id
WHERE district = 'California'
- Nick Wahlberg라는 배우가 출연한 모든 영화 목록 찾기
SELECT title, first_name, last_name
FROM film_actor
INNER JOIN actor ON film_actor.actor_id = actor.actor_id
INNER JOIN film ON film_actor.film_id = film.film_id
WHERE first_name = 'Nick' AND last_name = 'Wahlberg'
- 테니스 코트(facid 0, 1)의 2012년 9월 21일의 예약 시작시간 목록을 구하고 시작시간 오름차순으로 정렬하기
SELECT cd.bookings.starttime, cd.facilities.name
FROM cd.facilities INNER JOIN cd.bookings
ON cd.facilities.facid = cd.bookings.facid
WHERE cd.facilities.facid IN (0, 1)
AND cd.bookings.starttime >= '2012-09-21'
AND cd.bookings.starttime <= '2012-09-22'
ORDER BY cd.bookings.starttime
- David Farrell이란 회원의 예약 시작 시간을 구하기
SELECT cd.bookings.starttime
FROM cd.bookings INNER JOIN cd.members
ON cd.bookings.memid = cd.members.memid
WHERE cd.members.firstname = 'David' AND surname = 'Farrell'
UNION
- UNION 연산자는 두 개 이상의 SELECT문의 결과 세트를 결합하기 위해 사용된다.
- JOIN과 UNION의 기본적인 차이는 UNION은 두 결과를 직접 붙인다는 것이다.
SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2;
- UNION의 대상이 되는 SELECT문들이 논리적이어야 하고, 위에 결과를 쌓을 수 있도록 컬럼이 서로 일치해야 한다.
- 결과를
ORDER BY
로 정렬할 수 있다.
예제 테이블
Sales_2021_Q1 | |
---|
name | amount |
David | 100 |
Claire | 50 |
Sales_2021_Q2 | |
---|
name | amount |
David | 200 |
Claire | 100 |
SELECT * FROM Sales2021_Q1 UNION SELECT * FROM Sales2021_Q2;
Results
name amount
David 100
Claire 50
David 200
Claire 100
참고자료