SELECT 컬럼명 FROM 테이블1 AS A < INNER | LEFT | RIGHT | FULL > JOIN 테이블2 AS B -- 👆🏻 가독성을 위해 보통 테이블 명은 alias를 사용해 간단하게 표현해 사용합니다. ON A.foreign_key = B.id_key -- 👆🏻 조인 조건으로 A테이블의 외래키를 B테이블이 id_key라는 컬럼명으로 참조하고 있을 때, -- ON 으로 외래키와 참조키를 설정해주면, 두 컬럼을 비교해서 같은 값끼리 하나의 row로 나타내줍니다. [WHERE 조건식] [GROUP BY 컬럼명 혹은 표현식\ [HAVING 조건식] [ORDER BY 컬럼명]
🫥 프로그래머스 SQL 코딩테스트 - 저자 별 카테고리 별 매출액 집계하기 (lv.4)
- 테이블 3개를 JOIN하여 도서 판매 데이터를 기준으로 저자 별, 카테고리 별 매출액(
TOTAL_SALES
= 판매량 * 판매가) 을 구하여, 저자명, 카테고리, 매출액리스트를 출력하는 SQL문을 작성하는 문제입니다.SELECT A.author_name, B.category, sum(S.sales * B.price) AS total_sales FROM book AS B INNER JOIN book_sales AS S ON B.book_id = S.book_id INNER JOIN author AS A ON B.author_id = A.author_id GROUP BY A.author_id, B.category
JOIN을 사용할 때는 분석하여 조회하고자 하는 대상과 목표를 정확히 해야합니다.
SELECT로 조회할 컬럼명이 테이블1과 테이블2에 모두 있는 겹치는 이름이라면 점표기법을 사용해 테이블명.컬럼명
으로 명시해주어야 합니다. 이때 테이블명은 alias로 붙인 별칭으로 대신할 수 있습니다.
🪴 외래키 (Foreign Key)
- 테이블 간의 연결고리를 외래키라고 합니다. 다른 테이블의 특정 row를 식별하게 하는 컬럼이면서 해당 테이블에서 참조하고 있는 관계에 있는 컬럼을 말합니다.
- 참조하는 테이블은 자식테이블이라고 부르고, 참조를 당하는 테이블은 부모테이블이라고 부릅니다.
- 다른 테이블의 특정 row를 식별할 수 있어야 하므로 주로 primary key를 참조하는 경우가 많습니다.
- 외래키를 설정하면 테이블이 이상한 id값을 추가하려고 시도하면 에러를 발생시켜서 엉뚱한 row가 추가되는 것을 방지할 수 있습니다.
- 외래키가 아닌 컬럼을 기준으로도 조인 조건을 지정할 수 있습니다. (이 경우 JOIN 종류별로 결과가 모두 달라지게 됩니다.)
🪴 Alias
컬럼의 alias와 테이블의 alias에는 약간의 용도 차이가 존재합니다.
- 컬럼의 alias : 각 컬럼 이름이 실제로 테이블에 변환되어 보여지게 하기 위한 용도입니다.
- 테이블의 alias : SQL문의 전체 길이를 줄여서 코드의 가독성을 높이기 위한 용도로 실제로 테이블에서 보여지지 않습니다.
가장 많이 사용되는 조건입니다. 기준이 되는 테이블이 따로 없고 각 테이블에서 조인 조건으로 사용된 컬럼(ON으로 설정한 컬럼들)에 값이 둘 다 존재하는 경우, 즉 지정 조건을 만족하는 칼럼만 합칩니다. 따라서 기준 컬럼이 null값이 되는 경우가 없습니다. (쉽게 말해 테이블1과 테이블2의 교집합만 테이블로 만드는 것과 같습니다.)
🫥 프로그래머스 SQL 코딩테스트 - 조건에 맞는 도서와 저자 리스트 출력하기 (lv.2)
- 어느 한 서점에서 판매중인 도서들의 도서 정보(
BOOK
)테이블과 저자 정보(AUTHOR
) 테이블에서 '경제' 카테고리에 속하는 도서들의 도서 ID, 저자, 출판일 리스트를 출력하는 문제입니다.SELECT B.book_id, A.author_name, B.published_date FROM book B INNER JOIN author A ON B.author_id = A.author_id WHERE B.category = '경제';
INNER JOIN이 교집합적인 느낌이었다면, OUTER JOIN은 합집합 적인 성격을 띕니다. 조인 조건을 만족하지 않는 데이터까지 출력할 때 사용됩니다.
LEFT OUTER JOIN
: 테이블1을 기준(LEFT OUTER)으로 테이블2를 합치게 됩니다. 쉽게 표현하자면 테이블1에 테이블2의 데이터를 포함시키는 것입니다. 테이블1에는 있지만 테이블2에는 없는 값(조인 조건을 만족하지 않는 컬럼)은 NULL로 표현됩니다.
RIGHT OUTER JOIN
: 테이블2를 기준(RIGHT OUTER)으로 테이블1을 합치게 됩니다. 테이블2가 참조키를 가지는 테이블이므로 테이블1에만 있는 값은 제외됩니다.
FULL OUTER JOIN
: 두 테이블의 LEFT OUTER JOIIN
결과와 RIGHT OUTER JOIN
결과를 합치는 조인으로 결과에 모두 존재하는 row는 한 번만 표현해 줍니다.
🫥 프로그래머스 SQL 코딩테스트 - 오랜 기간 보호한 동물(1) (lv.3)
ANIMAL_INS
테이블은 동물 보호소에 들어온 동물의 정보를 담은 테이블입니다.ANIMAL_OUTS
테이블은 동물 보호소에서 입양 보낸 동물의 정보를 담은 테이블입니다.- 아직 입양을 못 간 동물 중, 가장 오래 보호소에 있었던 동물 3마리의 이름과 보호 시작일을 조회하기 위해
LEFT OUTER JOIN
을 사용하는 문제입니다.SELECT I.name, I.datetime FROM animal_ins AS I LEFT OUTER JOIN animal_outs AS O ON I.animal_id = O.animal_id WHERE O.animal_id IS NULL LIMIT 3;
🫥 프로그래머스 SQL 코딩테스트 - 오랜 기간 보호한 동물(2) (lv.3)
- 입양을 간 동물 중, 보호 기간이 가장 길었던 동물 두 마리의 아이디와 이름을 조회하는 문제입니다. 입양 보낸 동물들을 기준으로 테이블을 합쳐야 하기 때문에
RIGHT OUTER JOIN
을 사용하는 문제입니다- 보호기간을 구하기 위해
DATEDIFF
함수도 사용해야 하는 문제입니다.SELECT O.animal_id, O.name FROM animal_ins AS I RIGHT OUTER JOIN animal_outs AS O ON I.animal_id = O.animal_id GROUP BY O.animal_id ORDER BY DATEDIFF(O.datetime, I.datetime) DESC LIMIT 2;
NATURAL JOIN
: 두 테이블에서 이름이 같은 컬럼을 찾아서 자동으로 조인 조건을 설정해 INNER JOIN을 해주는 조인입니다. 즉, ON 조인 조건을 적지 않습니다. 하지만 테이블 구조를 모르는 사람이라면 어떤 컬럼을 기준으로 조인이 되었는지 알 수 없기 때문에 INNER JOIN을 사용해 ON을 명시해 주는 것이 더 좋습니다.CROSS JOIN
: 한 테이블의 하나의 row에 대해 다른 테이블의 모든 row들을 매칭하고, 그 다음 row에 대해서도 반복함으로써 두 테이블의 row들의 모든 조합을 보여주는 조인입니다. 이를 두 테이블의 cartesian product(두 집합의 모든 원소들의 조합을 나타내는 카르테시안 곱)을 구하는 조인이라고 합니다. 잘 쓰이지 않습니다. SELF JOIN
: 테이블이 자기 자신과 조인하는 경우입니다.Non-Equi JOIN
: ON 조인 조건에 동등 조건이 아닌 다른 종류의 조건을 사용해 조인할 수도 있습니다. 예컨대 부등호를 사용해 특정 시점 이후의 데이터를 구하거나 할 수 있습니다.SELECT 컬럼명 FROM 테이블1 INNER JOIN 테이블2 USING 겹치는 컬럼명
🫥 프로그래머스 SQL 코딩테스트 - 오프라인/온라인 판매 데이터 통합하기 (lv.4)
ONLINE_SALE
테이블과OFFLINE_SALE
테이블에서 2022년 3월의 오프라인/온라인 상품 판매 데이터의 판매 날짜, 상품ID, 유저ID, 판매량을 출력하는 SQL문을 작성하면서ONLINE_SALE
테이블에만 있는USER_ID
값은OFFLINE_SALE
데이터에서NULL
로 표시하는 문제입니다.SELECT sales_date, product_id, user_id, sales_amount FROM online_sale WHERE sales_date LIKE '2022-03%' UNION -- UNION을 사용해 테이블을 합칩니다. SELECT sales_date, product_id, NULL, sales_amount FROM offline_sale -- user_id 값으로 NULL을 채워서 컬럼의 수를 맞춰주었습니다. WHERE sales_date LIKE '2022-03%'