일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 백준 예산 자바
- 알고리즘
- 백준 접두사 로직
- 백준 2512 자바
- 백준 부분합 로직
- SQLD 정리
- SQLD 요약
- SQLD
- SQLD SQL 최적화 기본 원리
- 백준 동전1 자바
- 자바 문자열 예제
- 백준 2293 동전 1
- SQLD 책
- 백준 1141 로직
- 백준 2293 자바
- SQL 기본 및 활용
- 백준 1141
- 자바 DP 예제
- SQLD 내용
- BFS
- 자바 이분 탐색 예제
- 오라클 예제
- 백준 1141 접두사
- 백준
- 백준 예산 코드
- 자바 예제
- SQLD SQL 활용
- 백준 접두사 자바
- SQLD 내용 정리
- 너비우선탐색
- Today
- Total
혼자 공부하는 공간
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 활용 #2 본문
<목차>
<< 집합 연산자 >>
* 두 개 이상의 테이블에서 JOIN을 사용하지 않고 연관된 데이터를 조회하는 방법 중에 집합 연산자(Set Operation)를 사용하는 방법이 있다.
* 여러 SQL Query문의 결과를 연결하여 하나로 결합하는 방식을 사용한다.
* SELECT 절의 칼럼 수가 동일하고 SELECT 절의 동일 위치에 존재하는 칼럼의 데이터 타입이 상호 호환이 가능해야 한다. (반드시 동일할 필요는 없다.)
1. 집합 연산자의 종류
* UNION ALL 을 제외한 다른 집합 연산자에서는 SQL 문의 결과 집합에서 중복된 데이터 건들을 먼저 배제하는 작업을 수행한 후에 집합 연산을 적용한다.
2. 예시
* 아래의 문제들에 대해서 연습을 해볼 것이다.
-
K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀인 선수들과 '전남 드래곤즈' 팀인 선수들에 대한 내용을 모두 보고 싶다.
-
K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀인 선수들과 포지션이 골키퍼(GK)인 선수들을 모두 보고 싶다.
-
K-리그 소속 선수들에 대한 정보 중에서 포지션별 평균키와 팀별 평균키를 알고 싶다.
-
K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀이면서 포지션이 미드필더(MF)가 아닌 선수들의 정보를 보고 싶다.
-
K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀이면서 포지션이 골키퍼(GK)인 선수들의 정보를 보고 싶다.
* 위의 문제에 대한 SQL 문을 작성하기 전에 집합 연산자를 연습하기 위한 형태로 해석한다.
-
[합집합]
* K-리그 소속 선수 중 소속이 '삼성 블루윙즈' 팀인 선수들의 집합과
* K-리그 소속 선수 중 소속이 '전남 드래곤즈' 팀인 선수들의 집합의 합집합
-
[합집합]
* K-리그 소속 선수 중 소속이 '삼성 블루윙즈' 팀인 선수들의 집합과
* K-리그 소속 선수 중 포지션이 골키퍼(GK)인 선수들의 집합의 합집합
-
[합집합]
* K-리그 소속 선수 중 포지션별 평균키에 대한 집합과
* K-리그 소속 선수 중 팀별 평균키에 대한 집합의 합집합
-
[차집합]
* K-리그 소속 선수 중 소속이 '삼성 블루윙즈' 팀인 선수들의 집합과
* K-리그 소속 선수 중 포지션이 미드필더(MF)인 선수들의 집합의 차집합
-
[교집합]
* K-리그 소속 선수 중 소속이 '삼성 블루윙즈' 팀인 선수들의 집합과
* K-리그 소속 선수 중 포지션이 골키퍼(GK)인 선수들의 집합의 교집합
* 예시 - 문제 1
: K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀인 선수들과 '전남 드래곤즈' 팀인 선수들에 대한 내용을 모두 출력하라.
* 예시 - 결과 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
UNION
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K07';
/*
팀코드 선수명 포지션 백넘버 키
----- ------ ----- ------ ---
K02 가비 MF 10 177
K02 강대희 MF 26 174
K02 고종수 MF 22 176
K02 고창현 MF 8 170
K02 김강진 DF 43 181
K07 강철 DF 3 178
K07 김반 MF 14 174
K07 김영수 MF 30 175
K07 김정래 GK 33 185
K07 김창원 DF 5 183
.....
100개의 행이 선택되었다.
*/
|
cs |
---> 굳이 UNION을 사용하지 않고도 WHERE 절에 IN 이나 OR 키워드를 통해 같은 결과를 출력할 수 있다.
---> 하지만 IN/OR 키워드를 통해 출력하게 되면 결과 출력 순서가 달라질 수도 있기 때문에 ORDER BY 절을 통해 정렬 하는 것이 바람직하다.
* 예시 - 문제 2
: K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀인 선수들과 포지션이 골키퍼(GK)인 선수들을 모두 보고 싶다.
* 예시 - 결과 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
UNION
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE POSITION = 'GK';
/*
팀코드 선수명 포지션 백넘버 키
------ ----- ------ ---- ----
K01 권정혁 GK 1 195
K01 서동명 GK 21 196
K01 양지원 GK 45 181
K01 이무림 GK 31 185
K01 최창주 GK 40 187
K02 가비 MF 10 177
K02 강대희 MF 26 174
K02 고종수 MF 22 176
K02 고창현 MF 8 170
K02 김강진 DF 43 181
......
88개의 행이 선택되었다.
*/
|
cs |
---> 문제 1과 마찬가지로 굳이 UNION을 사용하지 않고 하나의 WHERE 절로도 같은 결과를 출력할 수 있다. 하지만 조건의 칼럼이 다르기 때문에 IN은 사용할 수 없고, OR을 통해서만 가능하다.
* 예시 - 문제 3
: K-리그 소속 선수들에 대한 정보 중에서 포지션별 평균키와 팀별 평균키를 알고 싶다.
* 예시 - 결과 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
SELECT 'P' 구분코드, POSITION 포지션, AVG(HEIGHT) 평균키
FROM PLAYER
GROUP BY POSITION
UNION
SELECT 'T' 구분코드, TEAM_ID 팀명, AVG(HEIGHT) 평균키
FROM PLAYER
GROUP BY TEAM_ID
ORDER BY 1;
/* ORDER BY 1은 SELECT의 칼럼set 중 첫 번째 칼럼에 대해서 정렬한다는 뜻() */
/*
구분코드 포지션 평균키
------- ------ --------
P DF 180.409
P FW 179.91
P GK 186.256
P MF 176.309
P TC 178.833
T K01 180.089
T K02 179.067
T K03 179.911
T K04 180.511
T K05 180.422
......
23개의 행이 선택되었다.
*/
|
cs |
---> 집합 연산자의 결과에서 두 번째 SELECT 절의 TEAM_ID는 '팀명' 으로 표기되어 있지만 실제로는 '포지션' 으로 출력되었다. 첫 번째 SELECT 절에서 사용된 HEADING이 적용되기 때문이다.
---> 그렇기 때문에 헷갈리지 않게 포지션별/팀별에 따라서 구분코드를 두었다.
* 예시 - 문제 4
: K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀이면서 포지션이 미드필더(MF)가 아닌 선수들의 정보를 보고 싶다.
* 예시 - 결과 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
MINUS
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE POSITION = 'MF'
ORDER BY 1, 2, 3, 4, 5;
/* TEAM_ID 기준 오름차순, 같으면 PLAYER_NAME 오름차순, 같으면 POSITION 오름차순, ...*/
/*
팀코드 선수명 포지션 백넘버 키
------ ------- ------ ----- ----
K02 김강진 DF 43 181
K02 김관희 FW 39 180
K02 김만근 FW 34 177
K02 김병국 DF 2 183
K02 김병근 DF 3 175
K02 왕선재 TC
K02 윤성효 TC
K02 윤화평 FW 42 182
K02 이성용 DF 20 173
K02 정광수 GK 41 182
.....
31개의 행이 선택되었다.
*/
|
cs |
---> Oracle : MINUS, SQL Server : EXCEPT 키워드 사용
---> 차집합 연산을 하지 않고 하나의 WHERE 절을 통해서도 같은 결과를 출력할 수 있다. TEAM_ID가 'K02' 인 조건과 POSITION이 'MF' 가 아닌 조건을 AND 연산으로 연결해준다.
(WHERE TEAM_ID = 'K02' AND NOT POSITION = 'MF';) 또는
(WHERE TEAM_ID = 'K02' AND POSITION <> 'MF';)
---> 또한 MINUS 연산자는 NOT EXISTS 또는 NOT IN 서브쿼리를 이용한 SQL문으로도 변경이 가능하다. (추후 링크)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER X
WHERE X.TEAM_ID = 'K02'
AND NOT EXISTS (
SELECT 1
FROM PLAYER Y
WHERE Y.PLAYER_ID = X.PLAYER_ID AND POSITION = 'MF'
)
ORDER BY 1, 2, 3, 4, 5;
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
AND PLAYER_ID NOT IN (
SELECT PLAYER_ID
FROM PLAYER
WHERE POSITION = 'MF'
)
ORDER BY 1, 2, 3, 4, 5;
/*
팀코드 선수명 포지션 백넘버 키
------ ------- ------ ----- ----
K02 김강진 DF 43 181
K02 김관희 FW 39 180
K02 김만근 FW 34 177
K02 김병국 DF 2 183
K02 김병근 DF 3 175
K02 왕선재 TC
K02 윤성효 TC
K02 윤화평 FW 42 182
K02 이성용 DF 20 173
K02 정광수 GK 41 182
.....
31개의 행이 선택되었다.
*/
|
cs |
* 예시 - 문제 5
: K-리그 소속 선수들 중에서 소속이 '삼성 블루윙즈' 팀이면서 포지션이 골키퍼(GK)인 선수들의 정보를 보고 싶다.
* 예시 - 결과 5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
INTERSECT
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE POSITION = 'GK'
ORDER BY 1, 2, 3, 4, 5;
/*
팀코드 선수명 포지션 백넘버 키
------ ------ ----- ------ ---
K02 김운재 GK 1 182
K02 정광수 GK 41 182
K02 조범철 GK 21 185
K02 최호진 GK 31 190
4개의 행이 선택되었다.
*/
|
cs |
---> INTERSECT 를 사용하지 않고도 하나의 WHERE 절을 통해 같은 결과를 출력할 수 있다. (AND)
(WHERE TEAM_ID = 'K02' AND POSITION = 'GK')
---> 또한 INTERSECT 연산자는 EXISTS 또는 IN 서브쿼리를 이용한 SQL문으로도 변경이 가능하다. (추후 링크)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER X
WHERE X.TEAM_ID = 'K02'
AND EXISTS (
SELECT 1
FROM PLAYER Y
WHERE Y.PLAYER_ID = X.PLAYER_ID
AND Y.POSITION = 'GK'
)
ORDER BY 1, 2, 3, 4, 5;
SELECT TEAM_ID 팀코드, PLAYER_NAME 선수명, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키
FROM PLAYER
WHERE TEAM_ID = 'K02'
AND PLAYER_ID IN (
SELECT PLAYER_ID
FROM PLAYER
WHERE POSITION = 'GK'
)
ORDER BY 1, 2, 3, 4, 5;
/*
팀코드 선수명 포지션 백넘버 키
------ ------ ----- ------ ---
K02 김운재 GK 1 182
K02 정광수 GK 41 182
K02 조범철 GK 21 185
K02 최호진 GK 31 190
4개의 행이 선택되었다.
*/
|
cs |
출처
질문은 댓글로 남겨주시면 되겠습니다. 감사합니다.
'자격증 > SQLD' 카테고리의 다른 글
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 활용 #4 (0) | 2020.08.30 |
---|---|
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 활용 #3 (0) | 2020.08.28 |
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 활용 #1 (0) | 2020.08.27 |
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 기본 #9 (0) | 2020.08.23 |
[SQL기본 및 활용] 2020년 SQLD 내용 정리 :: SQL 기본 #8 (0) | 2020.08.22 |