JOIN, UNION, 서브쿼리, GROUP BY, 집계 함, HAVING를 대표 예제와 함께 정리!
+프로그래머스에서 풀이한 문제도 업로드 예정
author 테이블: id (PK), name, email 등post 테이블: id (PK), author_id (FK), title, contents 등SELECT *
FROM author
INNER JOIN post ON author.id = post.author_id;
SELECT a.*, p.*
FROM author a
INNER JOIN post p ON a.id = p.author_id;
NULL로 표시됨.SELECT *
FROM author a
LEFT JOIN post p ON a.id = p.author_id;
SELECT *
FROM author a
RIGHT JOIN post p ON a.id = p.author_id;
| 조인 종류 | 설명 |
|---|---|
| INNER JOIN | 두 테이블 모두 조건에 맞는 행만 반환 (교집합) |
| LEFT JOIN | 왼쪽 테이블 전체 + 오른쪽 매칭 데이터, 매칭 없으면 NULL |
| RIGHT JOIN | 오른쪽 테이블 전체 + 왼쪽 매칭 데이터, 매칭 없으면 NULL |
| FULL OUTER JOIN | 왼쪽과 오른쪽 모두 포함 (MySQL은 지원하지 않음) |
SELECT * 대신 a.*, p.* 처럼 alias와 컬럼 명시를 권장한다.
SELECT 컬럼1, 컬럼2 FROM TABLE1
UNION
SELECT 컬럼1, 컬럼2 FROM TABLE2;
UNION은 중복 제거, UNION ALL은 중복 포함.SELECT *
FROM author
WHERE id IN (
SELECT author_id
FROM post
);
SELECT email,
(SELECT COUNT(*) FROM post p WHERE p.author_id = a.id) AS post_count
FROM author a;
SELECT a.*
FROM (SELECT * FROM author) AS a;
SELECT name, COUNT(*)
FROM author
GROUP BY name;
GROUP BY에 포함되지 않은 컬럼을 SELECT 할 경우 오류가 발생할 수 있음.예시: 글쓴이 ID별 그룹핑
SELECT author_id, COUNT(*) AS post_count
FROM post
GROUP BY author_id;
SELECT a.email, COUNT(p.id) AS post_count
FROM author a
LEFT JOIN post p ON a.id = p.author_id
GROUP BY a.email;
| 함수명 | 설명 | 예시 |
|---|---|---|
| COUNT() | 행 개수 세기 | SELECT COUNT(*) FROM author; |
| SUM() | 합계 | SELECT SUM(age) FROM author; |
| AVG() | 평균 | SELECT AVG(age) FROM author; |
| ROUND() | 소수점 반올림 | SELECT ROUND(AVG(age), 3) FROM author; |
| MIN() | 최솟값 | SELECT MIN(age) FROM author; |
| MAX() | 최댓값 | SELECT MAX(age) FROM author; |
SELECT name,
COUNT(*) AS '동명이인 수',
AVG(age) AS '동명이인의 평균 나이'
FROM author
GROUP BY name;
날짜별 게시글 수 출력 예시
SELECT DATE_FORMAT(created_time, '%Y-%m-%d') AS '날짜',
COUNT(*) AS '게시글 수'
FROM post
WHERE created_time IS NOT NULL
GROUP BY DATE_FORMAT(created_time, '%Y-%m-%d');
HAVING 절은 GROUP BY로 그룹화된 결과에 조건을 지정할 때 사용한다. WHERE 절은 그룹화 전에 전체 데이터를 필터링하는 역할을 한다.-- 글을 2번 이상 쓴 author_id 조회
SELECT author_id, COUNT(*)
FROM post
GROUP BY author_id
HAVING COUNT(*) >= 2;
HAVING은 집계 함수(COUNT, SUM, AVG 등)를 조건으로 직접 사용할 수 있다.-- 작성자(author_id)별로, 같은 제목(title)을 가진 글 개수 출력
SELECT author_id, title, COUNT(*)
FROM post
GROUP BY author_id, title;
HAVING은 반드시 GROUP BY와 함께 사용해야 한다. HAVING 조건에는 집계 함수뿐 아니라 컬럼 별칭도 사용할 수 있다(다만 DBMS에 따라 다를 수 있음). GROUP BY시 그룹화 순서에 따라 결과가 달라지므로 결과 의도를 명확히 해야 한다.[조건에 맞는 도서와 저자 리스트 출력하기]
https://school.programmers.co.kr/learn/courses/30/lessons/144854
[없어진 기록 찾기]
https://school.programmers.co.kr/learn/courses/30/lessons/59042
# JOIN만 사용
SELECT o.ANIMAL_ID, o.NAME
from ANIMAL_OUTS o
left join ANIMAL_INS i
on i.ANIMAL_ID=o.ANIMAL_ID
where i.ANIMAL_ID is null
order by o.ANIMAL_ID;
# 서브쿼리 풀이법(1)
SELECT ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME
FROM ANIMAL_OUTS
WHERE ANIMAL_OUTS.ANIMAL_ID NOT IN (
SELECT ANIMAL_INS.ANIMAL_ID
FROM ANIMAL_OUTS
INNER JOIN ANIMAL_INS
ON ANIMAL_OUTS.ANIMAL_ID = ANIMAL_INS.ANIMAL_ID
);
# 서브쿼리 풀이법(2)
select ANIMAL_OUTS.ANIMAL_ID, ANIMAL_OUTS.NAME
from ANIMAL_OUTS
where ANIMAL_OUTS.ANIMAL_ID not in(select ANIMAL_ID from ANIMAL_INS);
[자동차 종류 별 특정 옵션이 포함된 자동차 수 구하기]
https://school.programmers.co.kr/learn/courses/30/lessons/151137
[입양 시각 구하기(1)]00000000
https://school.programmers.co.kr/learn/courses/30/lessons/59412
# CAST 사용
SELECT HOUR(DATETIME) AS HOUR, COUNT(*) AS COUNT
FROM ANIMAL_OUTS
WHERE HOUR(DATETIME) >= 9
AND HOUR(DATETIME) < 20
GROUP BY HOUR(DATETIME)
ORDER BY HOUR(DATETIME);
#CAST 미사용
select CAST(date_format(DATETIME, '%H'), UNSIGNED) as HOUR, COUNT(*) as COUNT
from ANIMAL_OUTS
where CAST(date_format(DATETIME, '%H'), UNSIGNED) >= '09' and CAST(date_format(DATETIME, '%H'), UNSIGNED) < '20'
group by CAST(date_format(DATETIME, '%H'), UNSIGNED)
order by CAST(date_format(DATETIME, '%H'), UNSIGNED);
[동명 동물 수 찾기]
https://school.programmers.co.kr/learn/courses/30/lessons/59041
[카테고리 별 도서 판매량 집계하기]
https://school.programmers.co.kr/learn/courses/30/lessons/144855
# 모든책이 판매량이 있다면 inner join을 쓸 수 있지만 left join이 더 논리적으로 맞다고 생각함
-- inner join 풀이
select b.CATEGORY, sum(b_s.SALES) as TOTAL_SALES
from BOOK_SALES as b_s
inner join BOOK as b
on b_s.BOOK_ID = b.BOOK_ID
where date_format(b_s.SALES_DATE, '%Y-%m') = '2022-01'
group by b.CATEGORY
order by b.CATEGORY;
-- left join 풀이
select b.CATEGORY, sum(b_s.SALES) as TOTAL_SALES
from BOOK_SALES as b_s
left join BOOK as b
on b_s.BOOK_ID = b.BOOK_ID
where date_format(b_s.SALES_DATE, '%Y-%m') = '2022-01'
group by b.CATEGORY
order by b.CATEGORY;
[조건에 맞는 사용자와 총 거래금액 조회하기]
https://school.programmers.co.kr/learn/courses/30/lessons/164668
프로그래머스에서 다양한 예제 문제를 풀어보고 다른 사람들의 예제도 함께 보니 학습에 많은 도움이 되는듯
유연한 사고력을 기르는 연습이 필요할 듯!
이게 제일 복잡한듯요 정리감사