[포스코DX|SQL|4주] 17일차 수업
포스코DX X 비트교육센터 6기 - SQL
조인
식별관계, 비식별관계
- 식별 : 부모 테이블의 기본키 또는 유니크 키를 자식 테이블이 자신의 기본키로 사용
- 비식별 : 부모 테이블의 기본키 또는 유니크 키를 자신의 기본키로 사용하지 않고, 외래 키로 사용하는 관계 (주로 이거)
EER Diagram
erd 로 테이블 만든 다음.
Forward Engineer to Database에서
code 에 위 아래꺼 클릭하기
-- 테스트 데이터
insert into dept values(null, '총무');
insert into dept values(null, '개발');
insert into dept values(null, '영업');
insert into dept values(null, '기획');
select * from dept;
-- 테스트 데이터
insert into emp values(null, '둘리',1);
insert into emp values(null, '마이콜',2);
insert into emp values(null, '또치',3);
insert into emp values(null, '길동', null);
select * from emp;
-- inner join
select emp.name, dept.name
from emp join dept on emp.dept_no = dept.no;
-- left join(outer join)
select emp.name as '직원', ifnull(dept.name, '없음') as '부서'
from emp left join dept on emp.dept_no = dept.no;
-- left join(outer join)
select ifnull(emp.name, '없음') as '직원' , dept.name as '부서'
from emp right join dept on emp.dept_no = dept.no;
-- mysql에 full join 지원 XX
join
--
-- inner join
--
-- 예1) 현재 근무하고 있는 직원 사번과, 이름, 직책을 모두 출력
select a.emp_no, a.first_name, b.title
from employees a, titles b
where a.emp_no = b.emp_no -- join 조건 (n-1)
and b.to_date = '9999-01-01'; -- row 선택 조건
-- 예2) 현재, 근무하고 있는 직원 사번, 이름과 직책을 모두 출력하되
-- 여성 엔지니어(Engineer)만 출력
select a.emp_no, a.first_name, a.gender, b.title
from employees a, titles b
where a.emp_no = b.emp_no -- join 조건 (n-1)
and b.to_date = '9999-01-01' -- row 선택 조건1
and a.gender = 'f' -- row 선택 조건2
and b.title = 'Engineer'; -- row 선택 조건3
--
-- ANSI / ISO SQL1999 JOIN 표준 문법
--
-- 1) join ~ on *
-- 예: 현재, 직책별 평균 연봉을 큰 순서대로 출력
select a.title, avg(b.salary)
from titles a inner join salaries b on a.emp_no = b.emp_no
where a.to_date ='9999-01-01'
and b.to_date = '9999-01-01'
group by a.title
order by avg(b.salary) desc;
-- 2) Natural Join
-- 조인 대상이 되는 테이블들에 이름이 같은 공통 칼럼이 있는 경우
-- 조인 조건을 명시적으로 암묵적으로 조인이 된다. (자동으로)
-- 예: 현재 근무하고 있는 직원의 이름과 직책을 출력
select a.first_name, b.title
from employees a natural join titles b
where b.to_date = '9999-01-01'
order by a.first_name asc;
-- 3) join ~ using
-- natural join의 문제점
-- 예: 현재 근무하고 있는 직원의 직책과 연봉을 출력
select count(*)
from titles a natural join salaries b
where a.to_date = '9999-01-01'
and b.to_date = '9999-01-01';
-- 해결 1 : join ~using
select count(*)
from titles a join salaries b using(emp_no)
where a.to_date = '9999-01-01'
and b.to_date = '9999-01-01';
-- 해결 2 : join ~ on
select count(*)
from titles a join salaries b on a.emp_no = b.emp_no
where a.to_date = '9999-01-01'
and b.to_date = '9999-01-01';
-- 실습문제1
-- 현재, 직원별 근무 부서를 출력 해보세요.
-- 사번, 직원이름(first_name), 부서명만 출력
select a.emp_no, a.first_name, b.dept_name
from employees a, departments b, dept_emp c
where a.emp_no = c.emp_no
and b.dept_no = c.dept_no
and c.to_date = '9999-01-01';
-- 실습문제2
-- 현재, 직책별 평균연봉과 직원수를 구하되 직책별 직원수가 100명 이상인 직책만 출력하세요.alter
-- 직책, 평균연봉, 직원만 출력
select title, avg(salary), count(*)
from titles a, salaries b
where a.emp_no = b.emp_no
and a.to_date = '9999-01-01'
and b.to_date = '9999-01-01'
group by a.title
having count(*) >= 100;
-- 실습문제3
-- 현재, 부서별로 직책이 Engineer인 지원들에 대해서만 평균연봉을 구하세요.
-- 부서이름, 평균급여로 출력하고 평균연봉이 높은 순으로 정렬 하세요.
select a.dept_name, avg(d.salary)
from departments a, dept_emp b, titles c, salaries d
where a.dept_no = b.dept_no
and b.emp_no = c.emp_no
and c.emp_no = d.emp_no
and b.to_date = '9999-01-01'
and c.to_date = '9999-01-01'
and d.to_date = '9999-01-01'
and c.title = 'Engineer'
group by a.dept_name
order by avg(d.salary) desc;
서브 쿼리
--
-- subquery
--
--
-- 1) select절의 컬럼 프로젝션, insert into t value(...)
-- insert into t values() (서브쿼리)
--
--
-- 2) select의 from절의 서브쿼리
--
select a.n, a.s, a.r
from (select now() as n, sysdate() as s, 3+1 as r from dual) a;
--
-- 3) select의 where절(having절)의 서브쿼리
--
-- 예: 현재, Fai Bale이 근무하는 부서에서 근무하는 다른 직원의 사번, 이름을 출력
-- sol1) 절대 비추
select *
from employees a , dept_emp b
where a.emp_no = b.emp_no
and b.to_date ='9999-01-01'
and concat(first_name, ' ', last_name) = 'Fai Bale';
-- 'd004'
select a.emp_no, a.first_name
from employees a , dept_emp b
where a.emp_no = b.emp_no
and b.to_date ='9999-01-01'
and b.dept_no= 'd004';
-- sol2) subquery 사용
select a.emp_no, a.first_name
from employees a , dept_emp b
where a.emp_no = b.emp_no
and b.to_date ='9999-01-01'
and b.dept_no= (select b.dept_no
from employees a , dept_emp b
where a.emp_no = b.emp_no
and b.to_date ='9999-01-01'
and concat(first_name, ' ', last_name) = 'Fai Bale');
-- 3-1) 단일행 연산자: =,>,<, >=,<=,<>, !=
-- 예: 현제, 전체 사원의 평균 연봉보다 적은 급여를 받는 사원의 이름과 급여를 출력
select avg(salary) from salaries where to_date='9999-01-01';
select *
from employees a, salaries b
where a.emp_no=b.emp_no
and b.to_date = '9999-01-01'
and b.salary < (select avg(salary) from salaries where to_date='9999-01-01')
order by b.salary desc;
-- 예2: 현재, 가장 적은 평균 급여의 직책과 그 급여를 출력
-- Engineer 20000
-- sol1 ) having
select a.title , avg(b.salary) as avg_salary
from titles a, salaries b
where a.emp_no=b.emp_no
and b.to_date = '9999-01-01'
and a.to_date = '9999-01-01'
group by a.title
having avg_salary = (select min(avg_salary)
from ( select avg(b.salary) as avg_salary
from titles a, salaries b
where a.emp_no=b.emp_no
and b.to_date = '9999-01-01'
and a.to_date = '9999-01-01'
group by a.title) a);
select min(avg_salary)
from ( select avg(b.salary) as avg_salary
from titles a, salaries b
where a.emp_no=b.emp_no
and b.to_date = '9999-01-01'
and a.to_date = '9999-01-01'
group by a.title) a;
-- sol2) top-k
select a.title, avg(b.salary) as avg_salary
from titles a, salaries b
where a.emp_no = b.emp_no
and a.to_date = '9999-01-01'
and b.to_date = '9999-01-01'
group by a.title
order by avg_salary asc
limit 0,1;
-- 3-2) 복수행 연산자: in, not-in, 비교연산자any, 비교연산자all
-- any 사용법
-- 1. =any : in과 동일
-- 2. >any, >=any : 최소값
-- 3. <any, <=any : 최대값
-- 4. !=any, <>any : not in
-- all 사용법
-- 1. =all: (x)
-- 2. >all, >=all : 최대값
-- 3. <all, <=all : 최소값
-- 4. !=all, <>all
-- 예3) 현재, 급여가 50000 이상인 직원의 이름과 급여를 출력하세요. (급여가 내림차순)
-- sol) me
select a.first_name, b.salary
from employees a, salaries b
where a.emp_no = b.emp_no
and b.to_date = '9999-01-01'
having b.salary >= 50000
order by b.salary desc;
-- sol1) join
select a.first_name, b.salary
from employees a, salaries b
where a.emp_no = b.emp_no
and b.to_date = '9999-01-01'
and b.salary >= 50000
order by b.salary desc;
-- where( , ) in으로 풀기
select a.first_name, b.salary
from employees a, salaries b
where a.emp_no = b.emp_no
and b.to_date = '9999-01-01'
and (a.emp_no, b.salary) =any (select a.emp_no, b.salary
from employees a, salaries b
where a.emp_no = b.emp_no
and b.to_date = '9999-01-01'
and b.salary >= 50000)
order by b.salary asc;
-- 문제4: 현재, 각 부서별로 최고 급여를 받고 있는 직원의 이름과 연봉을 출력하세요.
select a.dept_no, max(b.salary)
from dept_emp a, salaries b
where a.emp_no = b.emp_no
and a.to_date = '9999-01-01'
and b.to_date ='9999-01-01'
group by a.dept_no;
-- sol1) where절 서브쿼리 in, 복수행 / 복수컬럼
select a.first_name, b.dept_no, c.dept_name, d.salary
from employees a, dept_emp b, departments c, salaries d
where a.emp_no = b.emp_no
and b.dept_no = c.dept_no
and a.emp_no = d.emp_no
and b.to_date = '9999-01-01'
and d.to_date = '9999-01-01'
and(b.dept_no, d.salary) in ( select a.dept_no, max(b.salary)
from dept_emp a, salaries b
where a.emp_no = b.emp_no
and a.to_date = '9999-01-01'
and b.to_date ='9999-01-01'
group by a.dept_no)
order by d.salary;
-- sol2) from절 서브쿼리, join
select c.dept_name, d.salary
from employees a, dept_emp b, departments c, salaries d
,( select a.dept_no , max(b.salary) as max_salary
from dept_emp a, salaries b
where a.emp_no = b.emp_no
and b.to_date = '9999-01-01'
and d.to_date = '9999-01-01' group by a.dept_no)
order by d.salary;
ddl
-- ddl
create table member(
no int not null auto_increment,
email varchar(200) not null,
password varchar(64) not null,
name varchar(100) not null,
department varchar(100),
primary key(no)
);
desc member;
alter table member add column juminbuho char(13) not null;
desc member;
alter table member drop column juminbuho;
desc member;
alter table member add column juminbuho char(13) not null after email;
desc member;
alter table member change column department dept varchar(200) not null;
desc member;
alter table member add self_intro text;
desc member;
alter table member drop column juminbuho;
desc member;
다음시간에 할 것
-
dml(insert, delete, update) + transaction
-
data modeling(DA, schema design) + Normalization(정규화 1NF, 2NF, 3NF)
-
JDBC Programming
월요일~토요일 평가과제 : dcl(bookmall사용자 만들기) + dml + jdbc programming - bookOnlineMall!!!!!
da + jdbc programming
bookmall.mwb