✅ AS – 컬럼 또는 테이블에 별칭 부여
SELECT name AS employee_name FROM employees;
SELECT SUM(amount) AS net_revenue FROM payment;
-- 특히 열에 함수를 적용할 때 유용
name 컬럼을 employee_name이라는 별칭으로 표시
AS는 무조건 결과나 이름을 바꾸려는 열이나 함수 뒤에 와야 함
특히 열에 함수를 적용할 때 유용
AS 연산자는 쿼리의 맨 마지막에 실행
total_spent는 output의 맨 마지막에 실행되기 때문에 WHERE, GROUP BY, HAVING절 등에서는 별칭을 사용할 수 없음
올바른 예시:
에러 예시:
✅ JOIN – 두 개 이상의 테이블 결합
SELECT employees.name, departments.department_name
FROM employees
JOIN departments ON employees.department_id = departments.id;
- employees 테이블과 departments 테이블을 department_id를 기준으로 결합
✅ INNER JOIN(or JOIN) – 두 테이블을 모두 충족하는 데이터만 결합
SELECT *
FROM TableA --TableB와
INNER JOIN TableB --TableA로 바꿔도 상관 없음
ON TableA.col_match = TableB.col_match; -- 결합 조건
두 테이블 모두에 있는 행만 가져옴
벤타이어그램이 대칭이라 두 테이블의 위치가 달라져도 상관 없음
Registrations 테이블(1, 2열)과 Logins 테이블(3, 4열)
reg_id | name | log_id | name |
1 | Andrew | 1 | Xavier |
2 | Bob | 2 | Andrew |
3 | Charlie | 3 | Yolanda |
4 | David | 4 | Bob |
위 테이블(왼쪽, Registrations / 오른쪽, Logins)에는 양쪽 테이블에 모두 있는 행(Andrew, Bob)이 있음
INNER JOIN을 수행하려면 어떤 열을 참조해야할 지 결정해야 함(
Registrations.name = Logins.name
부분)
INNER JOIN 결과 1:
SELECT * FROM Registrations
INNER JOIN Logins
ON Registrations.name = Logins.name
- Registrations 결과에서 모든 열을 선택하고 name 열을 기준으로 Logins에 INNER JOIN을 한 결과
reg_id | name | log_id | name |
1 | Andrew | 2 | Andrew |
2 | Bob | 4 | Bob |
INNER JOIN 결과 2:
SELECT reg_id, Logins.name, log_id
FROM Registrations
INNER JOIN Logins
ON Registrations.name = Logins.name -- 결합 조건
reg_id | name | log_id |
1 | Andrew | 2 |
2 | Bob | 4 |
SELECT
문에서Logins.name
으로 적는 이유name이 두 테이블 모두에 존재하기 때문
중복되지 않는 컬럼 이름이라면 어떤 테이블에 있는 것인지 명시할 필요 없이 그대로 쓰면 됨
SELECT payment_id, payment.customer_id, first_name FROM payment INNER JOIN customer ON payment.customer_id = customer.customer_id
PostgreSQL에서는 JOIN이라 적으면 INNER JOIN이 실행됨
✅ FULL (OUTER) JOIN – 모든 데이터 결합 (일치 여부 무관)
SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.col_match = TableB.col_match;
두 테이블에서 일치하는 데이터 + 일치하지 않는 데이터까지 모두 반환
(지원하지 않는 DBMS도 있음,UNION
을 사용해 구현 가능)TableA, TableB의 순서가 바뀌어도 완전한 대칭이라 상관 없음
SELECT * FROM Registrations
FULL OUTER JOIN Logins
ON Registrations.name = Logins.name
FULL (OUTER) JOIN 결과
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 |
- 전부 선택한 후, 한 테이블에만 존재하는 행에는 null 값을 입력
FULL (OUTER) JOIN with WHERE
SELECT * FROM TableA
FULL OUTER JOIN TableB
ON TableA.col_match = TableB.col_match
WHERE TableA.id IS null OR TableB.id IS null;
FULL OUTER JOIN에 WHERE문으로 자격을 부여하는 것
두 테이블에 모두 나와있지 않은 행을 구하는 것 (INNER JOIN과 반대 개념)
INNER JOIN과 마찬가지로 테이블의 위치는 서로 바뀌어도 결과는 같음
쓸 수 있는 상황:
새로운 개인정보 보호정책이 시행되어, 고객에게 첨부되지 않은 결제 정보나 결제에 첨부되지 않은 고객 정보를 가져오지 않도록 지정하려고 함
모든 결제 정보는 현재 고객과 관련되어 있고, 모든 고객 정보가 과거 결제 정보와 관련되어 있는지 확인하려고 함
비디오 가게라면, 이 비디오 가게에서 실제로 아무것도 빌리지 않은 사람의 고객 ID는 보유하려고 하지 않으려고 하는 상황
SELECT * FROM customer FULL OUTER JOIN payment ON customer.customer_id = payment.customer_id -- customer 테이블과 payment 테이블을 결합하여 customer_id를 결합 WHERE customer.customer_id IS null -- 결합한 테이블을 필터링해서 customer 테이블에만 고유한 행 찾기 OR payment.payment_id IS null
✅ LEFT (OUTER) JOIN – 왼쪽 테이블의 모든 데이터 포함
SELECT * FROM TableA -- 왼쪽 테이블
LEFT OUTER JOIN TableB -- 오른쪽 테이블
ON TableA.col_match = TableB.col_match;
TableA(왼쪽) 테이블의 모든 데이터 반환, TableB(오른쪽)에 일치하는 값이 없으면
NULL
TableB에만 속하는 정보는 가져오지 않음
벤다이어그램이 더 이상 대칭이 아니므로, 테이블의 순서가 중요
LEFT OUTER JOIN은 LEFT JOIN으로 줄여 작성 가능
LEFT (OUTER) JOIN 결과
reg_id | name | log_id | name |
1 | Andrew | 1 | Xavier |
2 | Bob | 2 | Andrew |
3 | Charlie | null | null |
4 | David | null | null |
- TableB(Login)에만 속하는 Xavier와 Yolanda는 표시되지 않음
LEFT(TableA, Registration)에만 속하는 정보만 표시(WHERE 사용)
SELECT * FROM TableA
LEFT OUTER JOIN TableB
ON TableA.col_match = TableB.col_match
WHERE TableB.id IS null;
결과
reg_id | name | log_id | name |
3 | Charlie | null | null |
4 | David | null | null |
- TableA(Registration)에만 해당되는 정보 결과를 보여줌
✅ RIGHT (OUTER) JOIN – 오른쪽 테이블의 모든 데이터 포함
SELECT * FROM TableA
RIGHT OUTER JOIN TableB
ON TableA.col_match = TableB.col_match;
TableB의 모든 데이터 반환, TableA에 일치하는 값이 없으면
NULL
TableB에만 있거나 TableB와 TableA 모두에 있는 행을 반환함(TableA에만 있는 행은 반환 X)
벤다이어그램이 더 이상 대칭이 아니므로, 테이블의 순서가 중요
RIGHT OUTER JOIN은 RIGHT JOIN으로 줄여 작성 가능
✅ UNION – 두 개 이상의 SELECT 결과 합치기
SELECT column_name FROM table1
UNION
SELECT column_name FROM table2;
table1과 table2에서 중복을 제거한 column_name 목록 반환
두 테이블의 열이 일치해야 함
원할 경우, UNION을 여러 번 불러서 여러 결과를 붙일 수 있음
그 외에도 ORDER BY를 이용해서 기준을 정해 정렬 및 분류가 가능
SELECT column_name FROM table1
UNION ALL
SELECT column_name FROM table2;
- 중복을 포함한 column_name 목록 반환 (
UNION ALL
)
✨ In English:
JOIN
combines data from multiple tables based on a common column.AS
assigns an alias to a column or table.INNER JOIN
returns only matching records from both tables.FULL OUTER JOIN
returns all records, whether they match or not.LEFT OUTER JOIN
returns all records from the left table and matching records from the right table.RIGHT JOIN
returns all records from the right table and matching records from the left table.UNION
merges the results of twoSELECT
queries, removing duplicates.UNION ALL
merges results without removing duplicates.
📝 오늘 배운 점:
JOIN
을 활용하면 여러 테이블의 데이터를 결합하여 보다 풍부한 정보를 얻을 수 있다.AS
는 컬럼이나 테이블 이름을 직관적으로 만들 때 유용하다.INNER JOIN
은 일치하는 데이터만 가져오므로 불필요한 데이터가 포함되지 않는다.FULL OUTER JOIN
은 모든 데이터를 가져와야 할 때 사용하지만 일부 DBMS에서는 지원하지 않는다.LEFT JOIN
과RIGHT JOIN
은 필요에 따라 NULL 값을 포함할 수 있어 데이터 분석 시 유용하다.UNION
을 사용하면 중복을 제거한 데이터를 가져올 수 있으며,UNION ALL
을 사용하면 중복까지 포함된다.적절한
JOIN
을 선택하는 것이 SQL 성능 최적화에 중요하다.
연습 문제
연습 문제 1
캘리포니아 판매세법이 개정되어 고객들에게 이 내용을 알려야 한다. 캘리포니아에 살고 있는 고객의 이메일은 무엇인가?
SELECT district, email FROM address INNER JOIN customer ON address.address_id = customer.address_id WHERE district = 'California';
처음에는 아무 생각 없이 FULL JOIN을 사용했는데, FULL JOIN을 사용하면 customer.email이 없는 경우도 결과에 포함될 수 있기 때문에, INNER JOIN을 사용하는 게 더 적절한 선택 같다.
INNER JOIN 특징
INNER JOIN
은 두 테이블에서 매칭되는 데이터만 반환즉,
customer.address_id = address.address_id
가 매칭되지 않으면 결과에서 제외됨(INNER JOIN
을 사용하면 주소와 고객 정보가 반드시 연결된 데이터만 조회됨)WHERE district = 'California'
조건을 추가하여 캘리포니아 지역만 필터링
연습 문제 2
Nick Wahlberg라는 배우의 광팬인 한 고객이 매장에 들어와서, 그가 출연한 영화를 찾고 싶다고 한다. Nick Wahlberg가 나오는 모든 영화 목록을 구하라.
SELECT title, first_name, last_name FROM film_actor INNER JOIN film ON film.film_id = film_actor.film_id INNER JOIN actor ON actor.actor_id = film_actor.actor_id -- 각 테이블을 연결할 때마다 JOIN ... ON을 명확히 적어줘야 함 WHERE actor.first_name='Nick' AND actor.last_name = 'Wahlberg'
SQL에서
INNER JOIN
을 사용할 때 여러 개의 테이블을 조인할 때는JOIN ... ON
을 각각 명확하게 지정해야 한다.film_actor
를 기준으로 조인 진행film_actor
는 중간 다리 역할을 하므로, 먼저 기준 테이블로 선택하는 것이 좋음벤다이어그램을 그려보면 조금 더 쉽게 접근할 수 있다