SQL 이론(5)
문제 : 사내의 최대 급여 및 최소 급여의 차이를 출력하시오
SELECT max(salary) - min(salary) from employees; ---
문제 : 매니저의 사번 및 그 매니저 밑 사원들 중 최소급여를 받는 사원의 급여를 출력하시오
매니저가 없는 사원들은 제외, 최소 급여가 5000미만인 경우는 제외한다, 급여 기준 역순으로 조회한다
SELECT manager_id, min(salary) from employees where manager_id is not null group by manager_id having min(salary) > 5000 order by min(salary);
문제 : 부서명, 부서위치id, 각 부서별 사원 총수, 각 부서 별 평균 급여를 출력하되, 부서위치를 오름차순으로 출력하시오
SELECT d.department_name, d.location_id, count(e.employee_id), avg(salary) from employees e, department d where e.department_id = d.department_id group by d.department_name, d.department_id order by d.location;
여기서 주목할 점은 count는 총수를 셀때 사용한다는 것과 count내부에도 조인한 컬럼이름을 써주어야한다는 것이다.
서브쿼리
문제 : 사원들 중에 Abel이라는 사원이 받는 급여보다 더 많은 급여를 받는 사원의 이름과 급여를 출력하시오
여기서 우리는 Abel이라는 사원의 급여를 모르기 때문에 이것을 찾을 수 있는 서브쿼리를 사용해야한다
select last_name, salary from employees where salary > (select salary from employees where last_name = 'Abel');
서브쿼리는 특정값을 모르는 경우 사용
또한 형식은 메인쿼리 - 서브쿼리로 이루어진다
서브쿼리 먼저 실행되고 그 결과값을 받아 메인쿼리가 실행된다
서브쿼리를 사용하게 된다면 셀프조인 기능을 대체할 수 있다
모든 값에 서브쿼리를 대입할 수 있지만 일단 group by에는 사용못한다고 생각
where절과 having절에 오는 서브쿼리
조건식 형식
where 조건식(column 연산자 값)
having 조건식(연산함수(column) 연산자 값)
여기서 서브쿼리가 들어가게 된다면 조건식의 값으로 사용되는 것!
서브쿼리가 값으로 대체된다는 소리는 조건식에 명시되어 있는 값을 모를때 사용
where, having절 서브쿼리는 반드시 비교대상인 값이 있어야하는데 모르기 때문에 사용해야한다
서브쿼리규칙
- 가로안에 서브쿼리가 들어간 형태
- where절과 having절에 사용되는 서브쿼리는 order by절 생략해야한다, 어차피 순서로 인해서 적용안되기 때문에 성능저하만 일어남
- 서브쿼리의 결과가 1개인 경우는 단일연산자, 결과가 복수인 경우는 in, 복수연산자 사용하기
서브쿼리 프로세스(작성할때 Tip)
- 현재 내가 무슨 값을 모르고 있는지?
- 모르는 값을 무엇으로 찾을 것인지?
- 서브쿼리를 통해서 select list절의 어떤 컬럼을 통해 모르는 값을 찾을 수 있을지
- 서브쿼리가 넘겨준 값(서브쿼리 결과)을 메인쿼리의 누가 받을 것인가
main쿼리에 where, having절에 어떤 컬럼을 명시할것인가 - main 쿼리의 조건식의 연산자를 결정
서브쿼리의 결과가 하나일때는 단일연산자, 두개 이상은 복수연산자 - 대부분의 서브쿼리의 컬럼과 메인쿼리 컬럼의 이름은 동일하다
데이터 타입이 같아야 성립되기 때문에!!
단일행 서브쿼리
한 행만 반환함, 단일행 비교 연산자 사용
select last_name, job_id from employees wher job_id = (select job_id from employees where employee_id = 141);
서브쿼리는 여러개가 들어가도 상관없음, and로 연결만 해주면 됨
select last_name, job_id, salary from employees where job_id = (select job_id from employees where employee_id = 141) and salary > (select salary from employees where employee_id = 143);
*주의할점 : 문장의 종결을 마지막 서브쿼리문에 해줘야함
문제 : 최저급여를 받는 사원의 이름과 업무, 급여를 출력하라
SELECT last_name, job_id, salary from employees where employee_id = (select employee_id from employees where min(salary);
문제 : it라는 부서에 근무하는 사원의 이름과 급여를 출력하시오
SELECT last_name, salary from employees where department_id = (select department_id from departments where departmenet_name = 'it');
having절에서 사용되는 서브쿼리, having절의 값으로 사용됨
select department_id, min(salary) from employees group by department_id having min(salary) > (select min(salary) from employees where department_id = 50);
주의
그리고 만약 서브쿼리 결과가 찾아지지 않는다면 메인쿼리에 null값을 보내준다. 우리는 null값에 오류를 발견하지 못할 가능성이 크다. 그러니까 서브쿼리 잘 작성하기!!
select employee_id, last_name
from employees
where salary = (select min(salary)
from employees
group by department_id);
이렇게 주면 오류가 뜬다. 왜냐하면 서브쿼리 결과는 다수이기에 여기서는 단일연산자 사용을 못한다
다중행 서브쿼리
: 서브쿼리가 복수의 결과값이 나오는 경우
간단하게 예를 들어서 비교하면 이렇게 된다
사실 이걸 하나씩 이해하기보다 외운다고 생각하는게 편하다!
코딩식으로 보게 된다면
select employee_id, last_name, job_id, salary from employees where salary < any (select salary from employees where job_id = 'IT_PROG') and job_id <> 'IT_PROG';
여기서 마지막에 job_id는 'IT_PROG'와 다르다라고 해주는 것은 결과값에는 IT_PROG를 빼줘야하기 때문에!!
문제 : Zlotkey 와 동일한 부서에 근무하는 다른 모든 사원들의 사번 및 고용날짜를 출력하시오
SELECT last_name, hire_date from employees where department_id in (select department_id from employees where last_naem = 'Zlotkey') and last_name <> 'Zlotkey';
주의
우리는 여기서 Zlotkey라는 사람이 단일결과일지 동명이인이 있어 복수의 결과가 나올지 모른다. 그렇기에 =을 사용하면 안되고 in을 사용해야한다. 현업에서도 그렇게 사용하는데 만약 결과값이 하나라고 확실한 경우에는 = 을 사용하는게 성능면에서 좋다.
문제 : 회사 전체 평균 급여보다 더 급여를 많이 받는 사원들의 사번 및 이름을 출력하시오
SELECT employee_id, last_name from employees where salary > (select avg(salary) from employees);
문제 : 이름에 u가 포함이 되는 사원들과 동일한 부서에 근무하는 사원들의 사번 및 이름을 출력하시오
SELECT employee_id, last_name from employees where department_id = (select department_id from employees where last_name like '%u%');
문제 : 시에틀이라는 도시에 근무하는 사원중 커미션을 받지 않은 모든 사람들의 이름, 부서명, 지역 ID를 출력하시오, 여기서 조인은 직원, 부서테이블만, 도시 스펠링은 Seattle
Select e.last_name, d.department_id, d.location_id from employees e, departments d where e.department_id = d.department_id and d.location_id = (select location_id from locations where city = 'Seattle') and e.commission_pct is null;
여기서 주의할점은 서브쿼리는 조인내역과 관계없다는 것!
대신 서브쿼리를 제외한 곳에는 조인해준 이름 써야한다
문제 : 이름이 DAVIES인 사람보다 후에 고용된 사원들의 이름 및 고용일자를 출력하시오,고용일자를 역순으로 출력하시오
SELECT last_name, hire_date from employees where hire_date > (select hire_date from employees where last_name = 'Davies') order by hire_date desc;
여기서 주의할점은 >이 아니라 DAVIES가 한명이상일것이라 생각해서 IN을 주게 된다면 그 두명의 데이비스 중에 한명의 데이터는 반영되지 않기에 애초에 그런 문제가 안나오겠지만 여기서는 한명이라는 조건을 가지고 있다 생각하기! 그리고 이름 형식 따라줘야함! 첫글자만 대문자
추가 서브쿼리 문제
1. 141번 사원과 동일한 업무를 수행하는 사원의 이름과 업무를 출력하시오
SELECT last_name, employee_id from employees where job_id = (select job_id from employees where employee_id = 141);
- Ernst와 동일한 부서에 근무하는 사원 중 급여가 5000보다 큰 사원의 이름과 급여를 출력하라
SELECT last_name, salary from employees where department_id = (select department_id from employees where last_name = 'Ernst') and salary > 5000;
- 이름에 t를 포함하고 있는 사원과 같은 부서에 근무하는 사원의 이름, 사원번호, 부서번호를 출력하시오
SELECT last_name, employee_id, department_id from employees where department_id in (select department_id from employees where last_name like '%t%'); *주의 : 여기서 결과값은 복수이니 in사용하기!!
- 최저급여를 받는 사원보다 더 많은 급여를 받는 사원의 이름과 급여를 찾아라
SELECT last_name, salary from employees where salary > (select min(salary) from employees);
*여기서 주의 : 컬럼 이름이 같은 경우가 많으나, 데이터 타입이 같은 경우 다른 컬럼 이름이 서브쿼리 select list절에 들어가는 경우도 있다
- king을 매니저로 두고 있는 모든 사원의 이름과 급여를 출력하라
SELECT last_name, salary from employees where manger_id = (select employee_id from employees where last_name = 'King'); 여기서 잘 생각해보면 킹의 사원번호가 사원의 매니저 번호가 되기 때문에 구조를 잘 이해하면서 풀어야한다
Author And Source
이 문제에 관하여(SQL 이론(5)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@doeunworld/SQL-이론5저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)