SQL Day 3_그룹화,집계함수,JOIN
Day 2 복습
- 숫자형 함수 중 양수, 0, 음수에 따라 1,0, -1을 반환해주는 함수는?
- 컬럼1과 컬럼2를 다른 형식으로 반환하고 싶다면 쓰는 문자형함수는?
- 파이썬에서 슬라이싱과 같은 문자형 함수 3가지는?
- 공백 혹은 일정 텍스트 제거 함수는?
- 연월일 반환, 시분초 반환 날짜형 함수는?
- NOW()와 SYSDATE() 차이는?
1. 오늘 배운 내용
데이터 그룹화(GROUP BY, DISTINCT), 집계함수, 총계출산 WITH ROLLUP, GROUPING( ) 함수, HAVING 절과 JOIN을 배웠다. 테이블 간의 연결이 안 되어 해보고 싶던 걸 못해서 이번 JOIN을 배우며 매우 반가웠다.
2. 이해하기 어려웠던 부분
A) JOIN
I'm deadly serious. 믿는 사람 소개로 연결..연결 이게 best인 거 같아요...
-- 형태
select *
from 테이블1 as 별칭1
join 테이블2 as 별칭2
on a.컬럼명1 = b.컬럼명2
a) 내부조인
- 다른 테이블과 연결하여 사용할 때 JOIN이 필요하다
- 한 테이블 내에서 연결하여 출력할 때 서브쿼리가 필요하다
select a.Population, a.Name, b.Name, b.Continent
from city a
join country b
on a.CountryCode = b.code
where b.Continent = 'europe'
order by a.Population
limit 1;
#455 Città del Vaticano Holy See (Vatican City State)
a) 외부조인
- left나 right를 쓰면 되는데 더 많은 값을 가진 쪽 방향으로 하면 된다.(부모 테이블로 향한다)
-- 형태
select *
from 테이블1 as 별칭1
left join 테이블2 as 별칭2 #left or right
on a.컬럼명1 = b.컬럼명2
3. 기억해야할 부분
1) 구별하여,
A) GROUP BY
- OO별 종합할 때 쓰기 좋은 문법이다.
- WHERE과 ORDER BY 사이에서 쓴다.
#박스오피스에서 2019년 개봉영화중 영화 유형별 최대/최소 매출액과 총매출액
select movie_type, max(sale_amt) as 최대매출액, min(sale_amt) as 최소매출액, sum(sale_amt) as 총매출액
from box_office where release_date like '2019%'
group by movie_type
order by sale_amt;
#대륙별 총면적이 넓고 총인구, 국가수가 많은 순으로
select continent, sum(SurfaceArea) as 총면적, sum(Population) as 총인구, count(*) as 국가수
from country group by continent order by 2 desc , 3 desc;
-- join과 활용
#부서별 평균봉급, 총 봉급, 인원수
select d.dept_name, avg(c.salary), sum(c.salary), count(a.emp_no)
from employees a
join dept_emp b on a.emp_no = b.emp_no
join salaries c on a.emp_no = c.emp_no
join departments d on b.dept_no = d.dept_no
group by b.dept_no;
a) DISTINCT(중복제거에도 사용)
- select 절 안에서 칼럼명 앞에 명시하면 그룹화와 비슷한 결과를 낼 수 있다.
- 중복 제거도 가능하다
- 다만, GROUP BY은 정렬까지 해준다.
B) HAVING 절 활용과 순서 지키기
- GROUP BY로 집계된 쿼리에서 조건에 맞는 값을 반환하고 싶을 때 사용한다.
- 그래서 GROUP BY 뒤에 와야 한다.
#개봉 월별로 순위가 탑10에 있는 영화 수 구하기 # 그룹내 조건걸기 having 탑텐 영화가 2편이상
select extract(year_month from release_date) as 개봉년월, count(*) 개봉편수
from box_office where ranks between 1 and 10
group by extract(year_month from release_date)
having count(*) > 1;
-- 서브쿼리에서 활용
select year(release_date),movie_name,sale_amt
from box_office where ranks =1 having sale_amt > (select avg(sale_amt) from box_office where ranks =1);
C) 한글 사용 에러
select if(grouping(b.name) = 1,'전체도시수',b.name), count(A.Name) as '도시 개수' #if와 grouping을 활용하여 전체도시개수 별칭 지정하기
from city a
join country b
on a.CountryCode = b.code
group by b.name with rollup
order by 2 desc;
전체도시를 별칭으로 정하니 1267 에러가 난다. 영어로 바꾸면 이상없다.
Error Code: 1267. Illegal mix of collations (utf8mb4_0900_ai_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'if' 0.000 sec...
2) 잘 쓸 거 같아,
A) 총계출산 WITH ROLLUP와 GROUPING( ) 함수
- 00별 집계를 하고 집계한 값의 총합 역시 나타내고 싶을 때 사용
- GROUP BY 컬럼명 WITH ROLLUP
- 다만, 값만 도출되고 명칭 없이 NULL 값으로 나온다.
- 그 NULL 값에 별칭을 정해주기 위해 IF와 GROUPING 함수를 활용한다.
- GROUPING( ) 함수의 반환값(1:총계, 0:소계)
-- 2019년 개봉작 중 영화유형별 매출액과 총합
select if(grouping(movie_type) = 1, '전체 총합', movie_type) 영화유형, sum(sale_amt) #if(조건,조건이 맞을시반환값, 조건이 다를시 반환값)
from box_office where release_date like '2019%' and quarter(release_date) = 1 and sale_amt >= 10000000
group by movie_type with rollup #총계출산
order by 1, 2 desc;
B) JOIN 사용시 외부키 활용
#박스오피스에서 2019년 개봉영화중 영화 유형별 최대/최소 매출액과 총매출액
select movie_type, max(sale_amt) as 최대매출액, min(sale_amt) as 최소매출액, sum(sale_amt) as 총매출액
from box_office where release_date like '2019%'
group by movie_type
order by sale_amt;
#대륙별 총면적이 넓고 총인구, 국가수가 많은 순으로
select continent, sum(SurfaceArea) as 총면적, sum(Population) as 총인구, count(*) as 국가수
from country group by continent order by 2 desc , 3 desc;
-- join과 활용
#부서별 평균봉급, 총 봉급, 인원수
select d.dept_name, avg(c.salary), sum(c.salary), count(a.emp_no)
from employees a
join dept_emp b on a.emp_no = b.emp_no
join salaries c on a.emp_no = c.emp_no
join departments d on b.dept_no = d.dept_no
group by b.dept_no;
#개봉 월별로 순위가 탑10에 있는 영화 수 구하기 # 그룹내 조건걸기 having 탑텐 영화가 2편이상
select extract(year_month from release_date) as 개봉년월, count(*) 개봉편수
from box_office where ranks between 1 and 10
group by extract(year_month from release_date)
having count(*) > 1;
-- 서브쿼리에서 활용
select year(release_date),movie_name,sale_amt
from box_office where ranks =1 having sale_amt > (select avg(sale_amt) from box_office where ranks =1);
select if(grouping(b.name) = 1,'전체도시수',b.name), count(A.Name) as '도시 개수' #if와 grouping을 활용하여 전체도시개수 별칭 지정하기
from city a
join country b
on a.CountryCode = b.code
group by b.name with rollup
order by 2 desc;
전체도시를 별칭으로 정하니 1267 에러가 난다. 영어로 바꾸면 이상없다.
Error Code: 1267. Illegal mix of collations (utf8mb4_0900_ai_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'if' 0.000 sec...
-- 2019년 개봉작 중 영화유형별 매출액과 총합
select if(grouping(movie_type) = 1, '전체 총합', movie_type) 영화유형, sum(sale_amt) #if(조건,조건이 맞을시반환값, 조건이 다를시 반환값)
from box_office where release_date like '2019%' and quarter(release_date) = 1 and sale_amt >= 10000000
group by movie_type with rollup #총계출산
order by 1, 2 desc;
- 직원과 관련된 건 emp_no와 부서와 관련된 건 dept_no로 연결되어 있다. 외부키로 다른 테이블과 연결하면 다른 테이블의 자료도 함께 사용할 수 있다.
#부서별 평균봉급, 총 봉급, 인원수
select d.dept_name, avg(c.salary), sum(c.salary), count(a.emp_no)
from employees a
join dept_emp b on a.emp_no = b.emp_no
join salaries c on a.emp_no = c.emp_no
join departments d on b.dept_no = d.dept_no
group by b.dept_no;
C) 집계함수
- count(),min( ), max(), avg() , SUM(), VAR_POP(), STDDEV_POP()
- 개수, 최솟값, 최댓값, 평균, 총합, 분산, 표준편차
- 단, 집계함수 사용시 자료가 꼬일 수 있다.
# 유럽에서 인구가 가장 작은 국가
select name, min(Population)
from country where Continent = 'europe';
#Holy See (Vatican City State) 1000 정답
# Albania 1000 오답: 가장 작은 인구는 맞지만 국가명과 매치하진 않는다, 단순위 맨 위 국가가 나왔다. 그래서 서브쿼리를 써야한다.
-- 서브쿼리 (한 테이블에서 집계쿼리 활용할 때)
select a.Name, b.min_Population
from (select min(Population) as min_Population from country where Continent = 'europe')b,
country a where a.Population = b.min_Population;
#Holy See (Vatican City State): 1000
-- join과 활용할 때도 서브쿼리가 필요하다.
# 세계에서 인구가 가장 작은 도시
select min(a.Population), a.Name, b.Name, b.Continent
from city a
join country b
on a.CountryCode = b.code
#42 Oranjestad Aruba North America (오답: 인구와 이름 미스매치)
# 파생 테이블 서브쿼리
select c.min_Population, a.Name, b.Name, b.Continent #인구와 이름 미스매치
from (select min(Population) as min_Population from city) c, city a
join country b
on a.CountryCode = b.code
where a.Population = c.min_Population;
#정답: 42 Adamstown Pitcairn Oceania
Author And Source
이 문제에 관하여(SQL Day 3_그룹화,집계함수,JOIN), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sungrok7/SQL-Day-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)