2021-12-08 12:44 작성
My SQL basic 메모
Table of contents
SELF JOIN 도입
SELF JOIN은 계층적 데이터를 쿼리할 때나 같은 table 내에서 한 row를 다른 rows와 비교할 때 종종 사용된다.
SELF JOIN을 사용할 때, table aliases(테이블 가명)을 사용해서 단일 쿼리에서 같은 table의 이름을 두 번 이상 반복하지 않도록 해야 한다.
하나의 쿼리에서 table aliases 없이 하나의 table을 두 번 혹은 그 이상 참조하는 것은 에러를 초래할 수 있다는 점에 주목하라.
예시
employees table은 employees 데이터 뿐만 아니라 조직 구조에 관한 데이터도 포함하고 있다. reportsto column은 한 employee의 manager id를 결정하는데 사용된다.
1) INNER JOIN을 사용해 SELF JOIN 하기
- 전체 조직 구조를 얻기 위해
employeestable 자체의employeeNumber와reportsTocolumns를 사용할 수 있다.employees표는 두 가지 역할을 가진다 - 하나는 Manager이고 다른 하나는 Direct Reports이다.
SELECT
CONCAT(m.lastName, ', ', m.firstName) AS Manager,
CONCAT(e.lastName, ', ', e.firstName) AS 'Direct report'
FROM
employees e
INNER JOIN employees m ON
m.employeeNumber = e.reportsTo
ORDER BY
Manager;
output:
| Manager | Direct report |
|---|---|
| Bondur, Gerard | Bondur, Loui |
| Bondur, Gerard | Gerard, Martin |
| Bondur, Gerard | Jones, Barry |
| Bondur, Gerard | Bott, Larry |
| Bondur, Gerard | Castillo, Pamela |
| Bondur, Gerard | Hernandez, Gerard |
| Bow, Anthony | Thompson, Leslie |
| Bow, Anthony | Firrelli, Julie |
…
위의 결과에서 employees와 manger가 매칭되는 데이터만 보여주므로 President를 볼 수는 없다. 왜냐하면 INNER JOIN으로 필터링 되었기 때문이다.
2) LEFT JOIN을 사용해 SELF JOIN 하기
President는 담당 manager도 없고 reportsTo column에서 대상도 존재하지 않아 NULL로 표시되는 employee를 의미한다.
다음의 구문에서는 LEFT JOIN 절을 이용해 President를 포함한다.
SELECT
IFNULL(CONCAT(m.lastname, ', ', m.firstname),
'Top Manager') AS 'Manager',
CONCAT(e.lastname, ', ', e.firstname) AS 'Direct report'
FROM
employees e
LEFT JOIN employees m ON
m.employeeNumber = e.reportsto
ORDER BY
manager DESC;
output:
| Manager | Direct report |
|---|---|
| Top Manager | Murphy, Diane |
| Patterson, William | King, Tom |
| Patterson, William | Marsh, Peter |
| Patterson, William | Fixter, Andy |
| Patterson, Mary | Patterson, William |
| Patterson, Mary | Bondur, Gerard |
| Patterson, Mary | Bow, Anthony |
| Patterson, Mary | Nishi, Mami |
| Nishi, Mami | Kato, Yoshimi |
…
3) SELF JOIN을 사용해 연속적인 rows를 비교하기
SELF JOIN을 사용해 같은 city 안에 있는 customers의 리스트를 뽑아낼 수 있다.
SELECT
c1.city,
c1.customerName,
c2.customerName
FROM
customers c1
INNER JOIN customers c2 ON
c1.city = c2.city
AND c1.customerName > c2.customerName
ORDER BY
c1.city;
output:
| city | customerName | customerName |
|---|---|---|
| Auckland | Kelly’s Gift Shop | GiftsForHim.com |
| Auckland | GiftsForHim.com | Down Under Souveniers, Inc |
| Auckland | Kelly’s Gift Shop | Down Under Souveniers, Inc |
| Boston | Gifts4AllAges.com | Diecast Collectables |
| Brickhaven | Online Mini Collectables | Collectables For Less Inc. |
| Brickhaven | Collectables For Less Inc. | Auto-Moto Classics Inc. |
| Brickhaven | Online Mini Collectables | Auto-Moto Classics Inc. |
| Cambridge | Marta’s Replicas Co. | Cambridge Collectables Co. |
| Frankfurt | Messner Shopping Network | Blauer See Auto, Co. |
…
c1.city = c2.city는 양 customers가 서로 같은 city인지 확인한다.c.customerName > c2.customerName은 같은 customer가 포함되지 않도록 한다.