INNER JOIN (+ 해커랭크 예제)
- JOIN이 필요한 이유
관계형 데이터베이스 RDBMS에서 데이터를 더 효율적으로 관리하기 위함
테이블을 따로 두고, 같은 값이 중복되지 않게
ex) 유저 아이디, 연락처, 배송 주소, 구매 상품, 상품 가격, 구매 개수 등이 쭉 나열되어 있음
아이디 | 연락처 | 주소 | 구매 상품 | 가격 | 개수 | 결제 수단 |
A | 010-****-1111 | 영등포구 여의도동 | NULL | NULL | NULL | NULL |
B | 010-****-2222 | 송파구 석촌동 | 샴푸 | 5000 | 1 | 국민카드 |
B | 010-****-2222 | 송파구 석촌동 | 식빵 | 6000 | 1 | 계좌이체 |
B | 010-****-2222 | 송파구 석촌동 | 티백 | 8000 | 4 | 국민카드 |
B | 010-****-2222 | 송파구 석촌동 | 냄비 | 7000 | 1 | 우리카드 |
B라는 고객은 구매 횟수가 많아서 아이디, 연락처, 주소 등이 계속 중복됨
이런식으로 한 테이블에 무수히 많은 데이터가 있으면 가독성이 떨어짐
테이블을 따로 두면
Users
ID | 로그인 아이디 | 연락처 | 주소 |
1 | A | 010-****-1111 | 영등포구 여의도동 |
2 | B | 010-****-2222 | 송파구 석촌동 |
Orders
UserID | 구매 상품 | 가격 | 개수 | 결제 수단 |
2 | 샴푸 | 5000 | 1 | 국민카드 |
2 | 식빵 | 6000 | 1 | 계좌이체 |
2 | 티백 | 8000 | 4 | 국민카드 |
2 | 냄비 | 7000 | 1 | 우리카드 |
윗 테이블의 보라색 영역이 사라지고 좀 더 효율적으로 데이터를 관리할 수 있음
나눠진 두 테이블을 합치려면 Users 테이블의 ID와 Orders 테이블의 UserID를 기준으로 연결
https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_join
- INNER JOIN
엑셀의 inner join이랑 개념은 동일
교집합만 출력해줌
SELECT *
FROM 테이블1
INNER JOIN 테이블2 ON (join의 기준이 되는 칼럼 ? = ?)
1. Customers와 Orders 테이블 CustomerID 기준으로 조인하기
SELECT *
FROM Orders
INNER JOIN Customers ON Customers.CustomerID = Orders.CustomerID
만약 Customers 테이블에는 1이라는 CustomerID가 있는데, Orders 테이블에는 1이 없으면 연결 기준이 사라지므로 해당 열은 출력 안됌
2. ShipperID로 join을 한번 더 하고 싶으면 이어서 써주기
SELECT *
FROM Orders
INNER JOIN Customers ON Customers.CustomerID = Orders.CustomerID
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
3. 테이블마다 쓰는 칼럼명이 다르다면?
ex) Customers 테이블에선 CustomerID인데, Orders에서는 id인 경우
>> 현업에서는 이런 경우가 더 흔하다. 테이블을 설계하는 사람이 한 명이 아니기도 하고, 서비스를 개편할 때마다 이름이 계속 달라지기 때문에
+) ERD (Entity Relationship Diagram) :데이터베이스 설계 과정에서 사용되는 모델링 기법 중 하나로, 데이터베이스에 저장될 데이터 엔티티(entity)들과 엔티티 간의 관계(relationship)를 시각적으로 표현한다.
>> 이 내용은 나중에 더 보충
- 해커랭크 예제 풀이 1
https://www.hackerrank.com/challenges/african-cities/problem?isFullScreen=true
African Cities | HackerRank
Query the names of all cities on the continent 'Africa'.
www.hackerrank.com
Given the CITY and COUNTRY tables, query the names of all cities where the CONTINENT is 'Africa'.
Note: CITY.CountryCode and COUNTRY.Code are matching key columns.
Input Format
The CITY and COUNTRY tables are described as follows:


풀이 접근
1. query the names of all cities >> 모든 데이터 다 필요한게 아니라 city의 name만 필요함
2. 두 테이블을 컨트리코드를 기준으로 연결 >> inner join
3. 근데 country 테이블에서는 continent가 Afica인 것만 출력 >> where문
SELECT name
FROM city
INNER JOIN country ON city.countrycode = country.code
WHERE country.continent = 'Africa'
>> 이렇게 실행시키면 에러가 남
-
ERROR 1052 (23000) at line 1: Column 'name' in field list is ambiguous
ambiguous한 이유: city에도 country에도 name이란 칼럼이 있기 때문에
따라서, 어느 테이블의 name인지 명시해줘야함
최종 코드
SELECT city.name
FROM city
INNER JOIN country ON CITY.CountryCode = COUNTRY.Code
WHERE country.continent = 'Africa'
- 해커랭크 예제 풀이 2
https://www.hackerrank.com/challenges/asian-population/problem?isFullScreen=true
Population Census | HackerRank
Query the sum of the populations of all cities on the continent 'Asia'.
www.hackerrank.com
Given the CITY and COUNTRY tables, query the sum of the populations of all cities where the CONTINENT is 'Asia'.
Note: CITY.CountryCode and COUNTRY.Code are matching key columns.
Input Format
The CITY and COUNTRY tables are described as follows:

풀이 접근
1. city와 country 테이블 code를 기준으로 조인 >> inner join
2. country에서 continent가 Asia인 모든 도시 >> where문 조건에 들어가기
3. 2번의 population sum을 출력 >> sum 사용
최종 코드
SELECT SUM(city.population)
FROM city
INNER JOIN country ON city.countrycode = country.code
WHERE country.continent = 'Asia'
- 해커랭크 예제 풀이 3 (JOIN 안 씀)
https://www.hackerrank.com/challenges/average-population/problem?isFullScreen=true
Average Population | HackerRank
Query the average population of all cities, rounded down to the nearest integer.
www.hackerrank.com
Query the average population for all cities in CITY, rounded down to the nearest integer.
Input Format
The CITY table is described as follows:

풀이 접근
1. city 테이블의 모든 도시의 인구 평균 >> AVG
2. 내림해서 정수로 만들기 >> floor, 소수점 첫 번째 자리에서
SELECT FLOOR(AVG(population))
FROM city
- 해커랭크 예제 풀이 4
https://www.hackerrank.com/challenges/average-population-of-each-continent/problem?isFullScreen=true
Average Population of Each Continent | HackerRank
Query the names of all continents and their respective city populations, rounded down to the nearest integer.
www.hackerrank.com
Given the CITY and COUNTRY tables, query the names of all the continents (COUNTRY.Continent) and their respective average city populations (CITY.Population) rounded down to the nearest integer.
Note: CITY.CountryCode and COUNTRY.Code are matching key columns.
Input Format
The CITY and COUNTRY tables are described as follows:

풀이 접근
1. city랑 country 테이블 연결 >> inner join
2. 밑처럼 continent 이름도 나와야 하고 각 continent마다 내림해서 정수로 만든 평균 인구수도 나와야 함 >> group by
3. group by에 쓴건 select에도 똑같이 써줘야 함, 집계 함수도 나란히
대륙 이름 | 평균 인구수 |
Asia | ~~ |
최종 코드
SELECT country.continent
, FLOOR(AVG(city.population))
FROM city
INNER JOIN country ON city.countrycode = country.code
GROUP BY country.continent
처음부터 완벽하게 작성 못하니까 우선 베이스 코드 짜놓고 다시 생각하고, 하나씩 수정해나가기