train 테이블
id | model | max_speed | production_year | first_class_places | second_class_places |
---|---|---|---|---|---|
1 | InterCity 100 | 160 | 2000 | 30 | 230 |
2 | InterCity 100 | 160 | 2000 | 40 | 210 |
3 | InterCity 125 | 200 | 2001 | 40 | 180 |
4 | Pendolino 390 | 240 | 2012 | 45 | 150 |
5 | Pendolino ETR310 | 240 | 2010 | 50 | 250 |
6 | Pendolino 390 | 240 | 2010 | 60 | 250 |
journey 테이블
id | train_id | route_id | date |
---|---|---|---|
1 | 1 | 1 | 2016-01-03 |
2 | 1 | 2 | 2016-01-04 |
3 | 1 | 3 | 2016-01-05 |
4 | 1 | 4 | 2016-01-06 |
5 | 2 | 2 | 2016-01-03 |
6 | 2 | 3 | 2016-01-04 |
7 | 2 | 4 | 2016-01-05 |
8 | 2 | 5 | 2016-01-06 |
9 | 3 | 3 | 2016-01-03 |
10 | 3 | 5 | 2016-01-04 |
11 | 3 | 5 | 2016-01-05 |
12 | 3 | 6 | 2016-01-06 |
13 | 4 | 4 | 2016-01-04 |
14 | 4 | 5 | 2016-01-04 |
15 | 4 | 6 | 2016-01-05 |
16 | 4 | 7 | 2016-01-06 |
17 | 5 | 2 | 2016-01-03 |
18 | 5 | 1 | 2016-01-05 |
19 | 5 | 3 | 2016-01-05 |
20 | 5 | 1 | 2016-01-06 |
21 | 6 | 3 | 2016-01-03 |
22 | 6 | 3 | 2016-01-04 |
23 | 6 | 1 | 2016-01-05 |
route 테이블
id | name | from_city | to_city | distance |
---|---|---|---|---|
1 | Manchester Express | Sheffield | Manchester | 60 |
2 | GoToLeads | Manchester | Leeds | 70 |
3 | StudentRoute | London | Oxford | 90 |
4 | MiddleEnglandWay | London | Leicester | 160 |
5 | BeatlesRoute | Liverpool | York | 160 |
6 | NewcastleDaily | York | Newcastle | 135 |
7 | ScotlandSpeed | Newcastle | Edinburgh | 200 |
train 테이블과 journey 테이블을 활용해 기차와 해당 기차의 여정에 관한 정보 추출
기차의 고유 아이디를 기준으로 2개의 테이블 조인
SELECT
t.id,
t.model,
j.*
FROM train AS t
INNER JOIN journey AS j
ON t.id = j.train_id
ORDER BY t.id;
→ 실행 결과:
Id | model | id | train_id | route_id | date |
---|---|---|---|---|---|
1 | InterCity 100 | 1 | 1 | 1 | 1/3/2016 |
1 | InterCity 100 | 25 | 1 | 5 | 1/3/2016 |
1 | InterCity 100 | 2 | 1 | 2 | 1/4/2016 |
1 | InterCity 100 | 3 | 1 | 3 | 1/5/2016 |
1 | InterCity 100 | 4 | 1 | 4 | 1/6/2016 |
2 | InterCity 100 | 6 | 2 | 3 | 1/4/2016 |
2 | InterCity 100 | 7 | 2 | 4 | 1/5/2016 |
2 | InterCity 100 | 8 | 2 | 5 | 1/6/2016 |
2 | InterCity 100 | 5 | 2 | 2 | 1/3/2016 |
3 | InterCity 125 | 10 | 3 | 5 | 1/4/2016 |
3 | InterCity 125 | 11 | 3 | 5 | 1/5/2016 |
3 | InterCity 125 | 29 | 3 | 4 | 1/3/2016 |
3 | InterCity 125 | 27 | 3 | 3 | 1/5/2016 |
3 | InterCity 125 | 12 | 3 | 6 | 1/6/2016 |
3 | InterCity 125 | 9 | 3 | 3 | 1/3/2016 |
4 | Pendolino 390 | 16 | 4 | 7 | 1/6/2016 |
4 | Pendolino 390 | 13 | 4 | 4 | 1/4/2016 |
4 | Pendolino 390 | 14 | 4 | 5 | 1/4/2016 |
4 | Pendolino 390 | 15 | 4 | 6 | 1/5/2016 |
4 | Pendolino 390 | 28 | 4 | 6 | 1/6/2016 |
GROUP BY를 활용해 쿼리문 작성
SELECT
t.id,
t.model,
COUNT(*) AS routes
FROM train
INNER JOIN journey AS j
ON t.id = j.train_id
GROUP BY t.id, t.model
ORDER BY t.id
→ 실행 결과:
id | model | routes |
---|---|---|
1 | InterCity 100 | 5 |
2 | InterCity 100 | 4 |
3 | InterCity 125 | 6 |
4 | Pendolino 390 | 5 |
결과만 보면 무엇이 달라졌는지 확실히 알 수 있음
집계 함수는 GROUP BY 없이도 사용할 수 있지만 대부분의 경우 집계 함수를 GROUP BY와 함께 사용함
💡 집계 함수 작동 원리
1. 동일한 값을 여러 개 갖고 있는 열의 이름을 GROUP BY 절에 적어줌으로써 데이터가 그룹 지어질 수 있는 기준으로 제공
2. 집계 함수가 동일한 값을 하나의 값으로 합치기 위해 그 행들의 값을 계산
3. 집계 함수를 통해 값을 합치는 과정에서 기존의 행들은 사라짐(집계 함수를 통해 구한 값들을 볼 수는 있어도 기존에 있던 정보를 함께 볼 수는 없음)
SELECT
t.id,
t.model,
r.name,
r.from_city,
r.to_city,
COUNT(*) OVER(PARTITION BY t.id ORDER BY t.id) AS routes,
COUNT(*) OVER() AS routes_total
FROM train AS t
INNER JOIN journey AS j
ON t.id = j.train_id
INNER JOIN route AS r
ON j.route_id = r.id;
→ 실행 결과:
Id | model | name | from_city | to_city | routes | routes_total |
---|---|---|---|---|---|---|
1 | InterCity 100 | Manchester Express | Sheffield | Manchester | 5 | 30 |
1 | InterCity 100 | BeatlesRoute | Liverpool | York | 5 | 30 |
1 | InterCity 100 | GoToLeads | Manchester | Leeds | 5 | 30 |
1 | InterCity 100 | StudentRoute | London | Oxford | 5 | 30 |
1 | InterCity 100 | MiddleEnglandWay | London | Leicester | 5 | 30 |
2 | InterCity 100 | StudentRoute | London | Oxford | 4 | 30 |
2 | InterCity 100 | MiddleEnglandWay | London | Leicester | 4 | 30 |
2 | InterCity 100 | BeatlesRoute | Liverpool | York | 4 | 30 |
2 | InterCity 100 | GoToLeads | Manchester | Leeds | 4 | 30 |
3 | InterCity 125 | BeatlesRoute | Liverpool | York | 6 | 30 |
3 | InterCity 125 | BeatlesRoute | Liverpool | York | 6 | 30 |
3 | InterCity 125 | MiddleEnglandWay | London | Leicester | 6 | 30 |
3 | InterCity 125 | StudentRoute | London | Oxford | 6 | 30 |
3 | InterCity 125 | NewcastleDaily | York | Newcastle | 6 | 30 |
3 | InterCity 125 | StudentRoute | London | Oxford | 6 | 30 |
4 | Pendolino 390 | ScotlandSpeed | Newcastle | Edinburgh | 5 | 30 |
4 | Pendolino 390 | MiddleEnglandWay | London | Leicester | 5 | 30 |
4 | Pendolino 390 | BeatlesRoute | Liverpool | York | 5 | 30 |
4 | Pendolino 390 | NewcastleDaily | York | Newcastle | 5 | 30 |
4 | Pendolino 390 | NewcastleDaily | York | Newcastle | 5 | 30 |
5 | Pendolino ETR310 | StudentRoute | London | Oxford | 5 | 30 |
COUNT(*) OVER() AS routes_total
은 집계되어야 할 행들끼리 구분 짓지 않았기 때문에 (PARTITION BY를 적지 않음) 모든 행이 집계 함수의 대상이 되어 30이라는 숫자가 모든 행마다 부여된 점COUNT(*) OVER(PARTITION BY t.id) ORDER BY t.id)) AS routes
부분