CHAPTER
1. 데이터 병합 및 결합
(1) UNION
(2) JOIN
2. 기타 데이터 조회 방법
(1) CONCAT
(2) ALIAS
(3) DISTINCT
(4) LIMIT
UNION은 여러 개의 SQL문을 합쳐서 하나의 SQL문으로 만들어주는 방법이다.
이때 주의해야할 점은 컬럼의 개수가 같아야 한다는 것이다.
UNION 문법에도 두 가지 종류가 있는데, 중복값의 출력 여부에 따라 다음과 같이 나뉜다.
SELECT column1, column2, ... FROM tableA
UNION | UNION ALL
SELECT column1, column2, ... FROM tableB;
두 개의 테스트용 테이블 생성해서 두 가지 문법의 차이 점을 확인해 보자.
# 테이블 생성
CREATE TABLE test1
(
no int
);
CREATE TABLE test2
(
no int
);
# 데이터 삽입
INSERT INTO test1 VALUES (1);
INSERT INTO test1 VALUES (2);
INSERT INTO test1 VALUES (3);
INSERT INTO test2 VALUES (5);
INSERT INTO test2 VALUES (6);
INSERT INTO test2 VALUES (3);
# 확인
SELECT * FROM test1;
SELECT * FROM test2;
SELECT * FROM test1
UNION ALL
SELECT * FROM test2;
SELECT * FROM test1
UNION
SELECT * FROM test2;
이번에는 지난 시간에 만든 'celeb' 테이블을 사용해서 몇 가지 예제를 확인해본다.
SELECT name, sex, agency FROM celeb WHERE sex='F'
UNION ALL
SELECT name, sex, agency FROM celeb WHERE agency='YG엔터테인먼트';
'UNION ALL'을 사용했기 때문에 두 쿼리에 공통되는 '이수현'데이터가 중복되었다.
SELECT name, sex, agency FROM celeb WHERE sex='F'
UNION
SELECT name, sex, agency FROM celeb WHERE agency='YG엔터테인먼트';
SELECT name, job_title FROM celeb WHERE job_title LIKE '%가수%'
UNION
SELECT name, birthday, age FROM celeb WHERE birthday BETWEEN '1980-01-01' AND '1980-12-31';
그런데 두 쿼리의 컬럼의 개수가 다르기 때문에 에러가 발생했다.
그래서 두 번째 쿼리의 'age'컬럼을 제거해서 두 쿼리의 개수를 맞춰주었다.
SELECT name, job_title FROM celeb WHERE job_title LIKE '%가수%'
UNION
SELECT name, birthday FROM celeb WHERE birthday BETWEEN '1980-01-01' AND '1980-12-31';
.
.
.
.
join은 두 테이블을 결합하는 것을 말한다. 합치는 방법에 따라 5가지가 있다.
그 전에 'celeb'테이블과 함께 실습한 'snl_show'테이블을 만들어 주었다. 테이블은 방송출연자와 그 정보를 담았다.
# 테이블 생성
CREATE TABLE snl_show
(
ID int NOT NULL AUTO_INCREMENT PRIMAEY KEY,
SEASON int NOT NULL,
EPISODE int NOT NULL,
BROADCAST_DATE date,
HOST varchar(32) NOT NULL
);
# 확인
DESC snl_show;
# 데이터 삽입
INSERT INTO snl_show VALUES (1, 8, 7, '2020-09-05', '강동원');
INSERT INTO snl_show VALUES (2, 8, 8, '2020-09-12', '유재석');
INSERT INTO snl_show VALUES (3, 8, 9, '2020-09-19', '차승원');
INSERT INTO snl_show VALUES (4, 8, 10, '2020-09-26', '이수현');
INSERT INTO snl_show VALUES (5, 9, 1, '2021-09-04', '이병현');
INSERT INTO snl_show VALUES (6, 9, 2, '2021-09-11', '하지원');
INSERT INTO snl_show VALUES (7, 9, 3, '2021-09-18', '제시');
INSERT INTO snl_show VALUES (8, 9, 4, '2021-09-25', '조정석');
INSERT INTO snl_show VALUES (9, 9, 5, '2021-10-02', '조여정');
INSERT INTO snl_show VALUES (10, 9, 6, '2021-10-09', '옥주현');
# 확인
SELECT * FROM snl_show;
이제 join의 종류를 'celeb'테이블과 함께 예시를 확인해 보면서 익혀보자.
INNER JOIN은 두 개의 테이블에서 공통된 요소들을 통해 결합하는 조인방식이다. 기본 문법을 살펴본 다음, 예제를 확인해보자.
SELECT col1, col2, ...
FROM tableA
INNER JOIN tableB
ON tableA.column = tableB.column
WHERE condition;
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
INNER JOIN snl_show
ON celeb.name = snl_show.host;
컬럼명을 조회할 때 겹치지 않는 컬럼의 경우에는 테이블명을 명시하지 않을 수 있지만, 겹치는 컬럼의 경우는 반드시 컬럼명을 명시해야 한다.
.
.
두 개의 테이블에서 공통영역을 포함해 왼쪽 테이블의 다른 데이터를 포함하는 조인방식이다.
SELECT col1, col2, ...
FROM tableA # left table
LEFT JOIN tableB # right table
ON tableA.column = tableB.column
WHERE condition;
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
LEFT JOIN snl_show
ON celeb.name = snl_show.host;
left table인 'celeb'테이블의 모든 데이터는 출력되지만 right table인 'snl_show'의 데이터는 'celeb'과 공통된 데이터만 출력할 수 있게 된다.
.
.
두 개의 테이블에서 공통영역을 포함해 오른쪽 테이블의 다른 데이터를 포함하는 조인방식이다.
SELECT col1, col2, ...
FROM tableA # left table
RIGHT JOIN tableB # right table
ON tableA.column = tableB.column
WHERE condition;
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
RIGHT JOIN snl_show
ON celeb.name = snl_show.host;
right table인 'snl_show'테이블의 모든 데이터는 출력되지만 left table인 'celeb'의 데이터는 'snl_show'와 공통된 데이터만 출력할 수 있게 된다.
.
.
두 개의 테이블에서 공통영역을 포함해 양쪽 테이블의 모든 데이터를 포함하는 조인방식이다.
SELECT col1, col2, ...
FROM tableA # left table
FULL OUTER JOIN tableB # right table
ON tableA.column = tableB.column
WHERE condition;
하지만 이러한 문법은 아쉽게도 MYSQL에서는 지원하지 않는다...
그래서 다음과 같은 문법 형식을 통해서 대체할 수 있다.
이와 같이 쓸 수 있는 이유는 UNION이 중복된 데이터를 제거하기 때문에 FULL OUTER JOIN을 할 수 있게 되는 것이다.
SELECT col1, col2, ...
FROM tableA
LEFT JOIN tableB ON tableA.column = tableB.column
UNION
SELECT col1, col2,...
FROM tableA
RIGHT JOIN tableB ON tableA.column = tableB.column
WHERE condition;
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
LEFT JOIN snl_show
ON celeb.name = snl_show.host
UNION
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb
RIGHT JOIN snl_show
ON celeb.name = snl_show.host;
.
.
SELF JOIN은 INNER JOIN과 같이 공통된 부분만 출력하는 조인 방식이지만, 그 기준을 WHERE절에 명시하는 차이점이 있다.
SELCT col1, col2,...
FROM tableA, tableB, ...
WHERE condition;
SELECT celeb.id, celeb.name, snl_show.id, snl_show.host
FROM celeb, snl_show
WHERE celeb.name = snl_show.host;
SELECT celeb.name, celeb.agency, celeb.job_title
FROM celeb, snl_show
WHERE celeb.name = snl_show.host AND celeb.agency='안테나';
SELECT celeb.name, celeb.age, celeb.job_title, celeb.agency, snl_show.season, snl_show.episode
FROM celeb, snl_show
WHERE celeb.name = celeb.host
AND (( NOT celeb.job_title LIKE '%영화배우% AND celeb.agency='YG엔터테인먼트)
OR (celeb.age>=40 AND celeb.agency != 'YG엔터테인먼트'));
SELECT celeb.name, snl_show.season, snl_show.episode, snl_show.broadcast_date, celeb.agency
FROM celeb, snl_show
WHERE celeb.name = snl_show.host
AND (snl_show.episode IN (7,9,10) OR agency='YG____' )
AND broadcast_date > 20200915;
SELECT celeb.id, celeb.name, celeb.job_title, snl_show.season, snl_show.episode
FROM celeb, snl_show
WHERE celeb.name = snl_show.host
AND NOT (celeb.job_title LIKE '%영화배우%' OR celeb.job_title LIKE '%탤런트%');
SELECT celeb.id, celeb.name, celeb.job_title, celeb.agency
FROM celeb, snl_show
WHERE celeb.name= snl_show.host
AND (snl_show.broadcast_date >= 20200915 OR NOT celeb.agency LIKE '%엔터테인먼트')
AND NOT (celeb.job_title LIKE '%영화배우%' OR celeb.job_title LIKE '%개그맨%');
.
.
.
.
여러 문자열을 하나로 합치거나 연결한다. 다음과 같은 문법으로 사용할 수 있다.
SELECT CONCAT('str1', 'str2', ...)
SELEECT CONCAT('concat', ' ', 'test');
SELECT CONCAT('이름: ', name) FROM celeb;
.
.
ALIAS는 칼럼이나 테이블 이름에 별칭 생성하는 코드이다.
이런 식으로 칼럼의 별칭을을 생성할 수도 있고,
SELECT column as alias
FROM tablename;
혹은 테이블의 별칭을 이와같이 생성할 수도 있다.
SELECT column1, column2
FROM tablename as alisa;
예제를 몇 가지 살펴보자.
SELECT name as '이름' FROM celeb;
SELECT name as '이름', agency as '소속사'
FROM celeb;
SELECT CONCAT (name, ' : ', job_title) as profile
FROM celeb;
SELECT s.season, s.episode, c.name, c.job_title
FROM celeb AS c, snl_show AS s
WHERE c.name = s.host;
이때 AS는 생략도 가능하다.
SELECT s.season, s.episode, c.name, c.job_title
FROM celeb c, snl_show s
WHERE c.name = s.host;
SELECT CONCAT(s.season, '-', s.episode, '(', s.broadcast_date, ')' ) AS '방송정보,
CONCAT(c.name, '(', c.job_title, ')' ) AS '출연자정보'
FROM celeb AS c, snl_show AS s
WHERE c.name = s.host;
SELECT CONCAT('이름: ', name, ', 소속사 : ', agency) as '연예인 정보'
FROM celeb
WHERE name LIKE '___';
SELECT c.agency as '소속사 정보',
CONCAT ('나이: ', c.age, ' (', c.sex, ')' ) as '신상정보',
CONCAT ( s.season, '-', s.episode, ' , 방송날짜: ', s.broadcast_date) as '출연정보'
FROM celeb AS c, snl_show AS s
WHERE c.name = s.host
AND c.agency LIKE '__엔터테인먼트'
ORDER BY s.broadcast_date DESC;
.
.
DISTINCT는 검색한 결과의 중복 제거해 주는 기능을 갖고 있다.
SELECT 조회문에 붙여서 사용할 수 있다.
SELECT DISTINCT column1, column2, ...
FROM tablename;
SELECT agency
FROM celeb;
중복 제거하면 다음과 같다.
SELECT DISTINCT agency
FROM celeb;
SELECT DISTINCT sex, job_title
FROM celeb;
WHERE job_title LIKE '%가수%';
.
.
LIMIT은 검색결과를 정렬된 순으로 주어진 숫자만큼만 조회하는 기능을 가진다.
코드의 마지막 줄에서 제한 숫자를 넣어주면 된다.
SELECT col1, col2, ...
FROM tablename
WHERE condition
LIMIT number;
SELECT *
FROM celeb
LIMIT 3;
SELECT *
FROM celeb
ORDER BY age
LIMIT 4;
SELECT *
FROM celeb
WHERE sex='M'
ORDER BY age DESC
LIMIT 2;
SELECT CONCAT ('SNL 시즌 ', s.season, ' 에피소드 ', s.episode, ' 호스트 ', c.name) as 'SNL 방송정보', c.age
FROM celeb as c, snl_show as s
WHERE c.name = s.host
ORDER BY c.age DESC
LIMIT 2;