테이블 간의 연결고리
우선 테이블 column간의 연관성을 파악하는 것이 중요하다
~stock (자식)테이블의 item_id가 item (부모)테이블의 id 컬럼을 참조하는 경우
이렇게 다른 테이블의 row를 식별해주는 컬럼을 Foreign Key(외래키)라고 한다
파악이 되었다면 Foreign Key를 설정해보자
table의 Setting에서 Foreign Keys를 선택하고 Foreign Key Name을 설정한다
item을 참조하는 stock의 fk이므로 ‘fk_stock_item’으로 지어준다
다음으로 Referenced Table을 클릭해 참조되는 Table을 선택하고 우측에서 컬럼들을 연결 짓는다
Apply!
이런 식으로 외래키 지정을 해 두면 이상한 row가 추가되는 것을 방지할 수 있다!
외래키 지정은 부모테이블 ~ 자식테이블 관계에서만 가능!
다른 종류의 테이블 조인하기
테이블 조인(join)이란 여러 테이블을 합쳐서 하나의 테이블처럼 보는 것이다
SELECT
item.id,
item.name,
stock.item_id,
stock.inventory_count
FROM item LEFT OUTER JOIN stock
ON item.id = stock.item_id
FROM A LEFT OUTER JOIN B
ON a = b -> A테이블을 기준으로 B테이블이 동일한 a, b 컬럼 값으로 대응되며 합쳐짐
FROM A RIGHT OUTER JOIN B
ON a = b -> B테이블을 기준으로 A테이블이 동일한 a, b 컬럼 값으로 대응되며 합쳐짐
*컬럼 이름이 동일하다면 USING(id)라고 써도 된다
테이블을 합친 후 알아보기 쉽게 테이블에 alias를 붙어보자
SELECT
i.id,
i.name,
s.item_id,
s.inventory_count
FROM item AS i LEFT OUTER JOIN stock AS s
ON item.id = stock.item_id
이렇게 AS로 alias를 지정하고 코드의 모든 절에 동일하게 수정해줘야 한다
*컬럼에 붙이는 alias와 달리 표에 나타나지는 않는다.
단순히 코드 가독성, 서로 다른 테이블에 같은 이름의 컬럼을 구별하려는 목적이다
SELECT
item.id,
item.name,
stock.item_id,
stock.inventory_count
FROM item INNER JOIN stock
ON item.id = stock.item_id
FROM A INNER JOIN B
ON a = b -> 기준 없이 합치고, 값이 겹쳐지는 컬럼만 보여준다(Null X)
*Foreign Key를 기준으로 합쳤다면 RIGHT OUTER JOIN과 INNER JOIN결과가 같을 수 밖에 없다!
물론 반드시 부모 자식 관계가 아닌 table이라도 공통요소가 보인다면 합칠 수 있다!
그런 경우 RIGHT OUTER JOIN/LEFT OUTER JOIN/INNER JOIN의 결과가 각각 다를 것
이렇게 다른 종류의 테이블을 가로방향으로 합치는 것을 ‘결합 연산’이라고 한다
같은 종류의 테이블 조인하기
같은 종류의 테이블을 세로방향으로 합치는 ‘집합 연산’에 대해서 알아보자
말 그대로 row들을 원소로 가지는 두 집합의 합집합, 차집합, 교집합을 구한다고 생각하면 간단!
*INTERSECT와 MINUS는 MySQL에서 지원하지 않는다!
JOIN을 통해서 간접적인 결과를 얻자~
UNION -> 교집합이 존재하는 같은 종류의 두 테이블을 합칠 때 사용!
SELECT * FROM item
UNION
SELECT * FROM item_new
UNION ALL -> 교집합을 고려하지 않고 그냥 두 테이블을 합칠 때 사용!
사실 다른 종류의 테이블도 조회하는 컬럼만 일치시키면 집합 연산이 가능하다
서로 다른 3개의 테이블 조인하기
이 경우 review 테이블에 2개의 Foreign Key 설정이 가능
SELECT
i.name, i.id,
r.item_id, r.star, r.comment, r.mem_id,
m.id, m.email
FROM
item As i LEFT OUTER JOIN review AS r
ON r.item_id = i.id
LEFT OUTER JOIN member AS m
ON r.mem_id = m.id;
이제, 여기서 의미 있는 데이터를 추출해보자
ex) 각 상품별로 여성회원들이 남긴 별점의 평균값, 리뷰 수 구하기 (리뷰가 하나인 경우 제외)
SELECT i.id, i.name, AVG(star), COUNT(*)
FROM
item AS i LEFT OUTER JOIN review AS r
ON r.item_id = i.id
LEFT OUTER JOIN member AS m
ON r.mem_id = m.id
WHERE m.gender = 'f'
GROUP BY i.id, i.name
HAVING COUNT(*) > 1
ORDER BY
AVG(star) DESC,
COUNT(*) DESC;
ex) 이번에는 남녀 공용 상품의 등록 연도별 평균 별점을 구해보자
SELECT
YEAR(i.registration_date) AS '등록 연도',
COUNT(*) AS '리뷰 개수',
AVG(star) AS '별점 평균값'
FROM
item AS i INNER JOIN review AS r
ON i.id = r.item_id
INNER JOIN member AS m
ON r.mem_id = m.id
WHERE i.gender = 'u'
GROUP BY YEAR(i.registration_date)
HAVING COUNT(*) > 10
ORDER BY AVG(star) DESC;
이 외에도 NATURAL JOIN, CROSS JOIN, SELF JOIN, FULL OUTER JOIN, NON-Equi JOIN 등이 있다..
본 내용은 Codeit의 '개발자를 위한 SQL 데이터베이스'를 바탕으로 작성되었습니다.
'Computer Science > Database, SQL' 카테고리의 다른 글
[HUFS/데이터베이스] #1 데이터베이스 환경 (6) | 2021.09.01 |
---|---|
[Codeit/MySQL] #6 서브쿼리와 뷰를 활용한 데이터 분석 (11) | 2021.04.16 |
[Codeit/MySQL] #4 데이터 분석 입문 (0) | 2021.04.16 |
[Codeit/MySQL] #3 데이터 조회 (4) | 2021.04.15 |
[Codeit/MySQL] #2 테이블 생성 (4) | 2021.04.15 |