210817 월
3. 교차조인(CROSS JOIN, 카티지언 곱)
: 조인되는 테이블의 각 행들이 모드 매핑 된 데이터가 검색 되는 방법
SELECT
EMP_NAME
, DEPT_TITLE
FROM EMPLOYEE
CROSS JOIN DEPARTMENT;
--결국 SELECT... FROM EMPLOYEE, DEPARTMENT;와 같다
4. 비등가조인(NON EQUAL JOIN)
: '=' 등호를 사용하지 않는 조인문
-지정한 컬럼 값이 일치하는 경우가 아닌, 값의 범위에 포함된느 행들을 연결하는 방식
4-1) ANSI
SELECT
EMP_NAME
, SALARY
, E.SAL_LEVEL
, S.SAL_LEVEL
FROM EMPLOYEE E
JOIN SAL_GRADE S ON(SALARY BETWEEN MIN_SAL AND MAX_SAL);
4-2) ORACLE
SELECT
EMP_NAME
, SALARY
, E.SAL_LEVEL
, S.SAL_LEVEL
FROM EMPLOYEE E, SAL_GRADE S
WHERE SALARY BETWEEN MIN_SAL AND MAX_SAL;
5. 자체 조인(SELF JOIN)
: 같은 테이블을 조인. 자기 자신과 조인을 맺음.
5-1) ANSI
SELECT
E.EMP_ID 사원사번
, E.EMP_NAME 사원이름
, E.MANAGER_ID 관리자사번
, M.EMP_NAME 관리자이름
FROM EMPLOYEE E
JOIN EMPLOYEE M ON(E.MANAGER_ID = M.EMP_ID);
5-2) ORACLE
SELECT
E.EMP_ID 사원사번
, E.EMP_NAME 사원이름
, E.MANAGER_ID 관리자사번
, M.EMP_NAME 관리자이름
FROM EMPLOYEE E, EMPLOYEE M
WHERE E.MANAGER_ID = M.EMP_ID;
6. 다중조인
6-1) ORACLE
SELECT
EMP_ID
, EMP_NAME
, DEPT_CODE
,DEPT_TITLE
, LOCAL_NAME
FROM EMPLOYEE
JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID)
JOIN LOCATION ON(LOCATION_ID = LOCAL_CODE);
--**JOIN순서를 바꾸면 되지 않음
--JOIN LOCATION ON(LOCATION_ID = LOCAL_CODE)
--JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); -> 이거는 실행 불가능
6-2) ANSI
SELECT
EMP_ID
, EMP_NAME
, DEPT_CODE
, DEPT_TITLE
, LOCAL_NAME
FROM EMPLOYEE, DEPARTMENT, LOCATION
WHERE DEPT_CODE = DEPT_ID
AND LOCATION_ID = LOCAL_CODE;
SUBQUERY(서브쿼리)
: 하나의 SQL문 안에 포함된 또 다른 SQL문, 메인 쿼리를 위해 보조 역할을 하는 쿼리문
-서브 쿼리를 괄호로 감싸서 이용함
1. 부서 코드가 노옹철 사원과 같은 부서 소속의 직원 명단 조회
1-1) 사원명이 노옹철인 사람의 부서 조회
SELECT
DEPT_CODE
FROM EMPLOYEE
WHERE EMP_NAME = '노옹철';
1-2) 부서코드가 D9인 직원 명단 조회
SELECT
*
FROM EMPLOYEE
WHERE DEPT_CODE = 'D9';
1-3) 부서코드가 노옹철 사원과 같은 소속의 직원 명단 조회
SELECT
*
FROM EMPLOYEE
WHERE DEPT_CODE = (SELECT
DEPT_CODE
FROM EMPLOYEE
WHERE EMP_NAME = '노옹철');
2. 전 직원의 평균 급여보다 많은 급여를 받고 있는 직원의 사번, 이름, 직급코드, 급여 조회
1) 전 직원의 평균 급여 조회
SELECT
AVG(SALARY)
FROM EMPLOYEE;
2) 평균 급여보다 많이 받는 직원 조회
SELECT
EMP_ID
, EMP_NAME
, JOB_CODE
, SALARY
FROM EMPLOYEE
WHERE SALARY > (SELECT
AVG(SALARY)
FROM EMPLOYEE);
--> 서브 쿼리는 알려지지 않은 기준을 이용한 검색을 위해서 사용함
3) 단일행 서브쿼리(Single Row Subquery)
: 서브쿼리의 조회 결과 값의 행이 1개일 때, 단일행 서브쿼리 앞에는 일반 연산자 사용
<, >, <=, >=, =, !=/^=/<>
3-1) 가장 적은 급여를 받는 직원의 사번, 이름, 직급, 부서, 급여 조회
SELECT
EMP_ID, EMP_NAME, JOB_CODE, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY = (SELECT MIN(SALARY) FROM EMPLOYEE);
--WHERE MIN(SALARY);이건 안됨
*서브쿼리는 WHERE절 뿐만 아니라 SELECT, HAVING, FROM절에서도 사용할 수 있음
3-2) 부서별(부서가 없는 사람 포함) 급여의 합계 중 가장 큰 부서의 부서명, 급여 합계를 조회
1) 부서별 급여 합계
SELECT DEPT_TITLE, SUM(SALARY)
FROM EMPLOYEE
--부서 코드가 NULL인 사원도 있으므로 전 직원에 대한 조회를 위해 LETF OUTER JOIN
LEFT JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID)
GROUP BY DEPT_TITLE;
(2) 급여 합계가 가장 큰 부서의 급여 합계 값
SELECT
MAX(SUM(SALARY))
FROM EMPLOYEE
GROUP BY DEPT_CODE;
(3) 부서별 급여 합계 중 가장 큰 합계를 가진 부서 조회
SELECT DEPT_TITLE, SUM(SALARY)
FROM EMPLOYEE
--부서 코드가 NULL인 사원도 있으므로 전 직원에 대한 조회를 위해 LETF OUTER JOIN
LEFT JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID)
GROUP BY DEPT_TITLE
HAVING SUM(SALARY) = (SELECT
MAX(SUM(SALARY))
FROM EMPLOYEE
GROUP BY DEPT_CODE);
2) 다중행 서브쿼리(Multi Row Subquery)
: 서브 쿼리의 조회 결과 행의 개수가 여러 개일 때
-다중행 서브쿼리 앞에는 일반 연산자 사용할 수 없음
*single-row subquery returns more than one row => 일반 연산자 사용시 발생하는 오류
(1) IN / NOT IN : 여러 개의 결과 값 중에서 한개라도 일치하는 값이 있다면 혹은 없다면
(2) ANY / < ANY : 여러 개의 결과값 중 한개라도 큰 / 작은 경우
(3) ALL / < ALL : 모든 값보다 큰 / 작은 경우
(4) EXISTS / NOT EXISTS : 여러 개의 결과값 중 해당 값이 존재하는지
2-1) 부서별 최고 급여를 받는 직원의 이름, 직급, 부서, 급여 조회(부서순 정렬)
SELECT
EMP_NAME,
JOB_CODE,
SALARY
FROM EMPLOYEE
WHERE SALARY IN (SELECT MAX(SALARY) FROM EMPLOYEE GROUP BY DEPT_CODE)
--WHERE SALARY = (SELECT MAX(SALARY) FROM EMPLOYEE GROUP BY DEPT_CODE)
--single-row subquery returns more than one row => IN이 아닌 = 연산자 사용시 발생
ORDER BY 3;
2-2) 대리 직급의 직원들 중에서 과장 직급의 최소 급여보다 많이 받는 직원의 사번, 이름, 직급, 급여를 조회
단, > ANY 혹은 < ANY 연산자를 사용
(1) 급여가 200만원 이상인 대리 직급 직원 조회
SELECT
EMP_ID
, EMP_NAME
, JOB_NAME
, SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '대리'
AND SALARY >= 2000000;
(2) 과장 직급 직원의 급여
SELECT
SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '과장';
(3) 대리 직급의 직원들 중에서 과장 직급의 최소 급여보다 많이 받는 직원
SELECT
EMP_ID
, EMP_NAME
, JOB_NAME
, SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '대리'
AND SALARY > ANY (SELECT
SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '과장');
--여기는 일반 연산자는 안됨
(4) 차장 직급의 급여의 가장 큰 값보다 많이 받는 과장 직급의 직원
-사번, 이름, 직급, 급여 조회
-단, > ALL 또는 < ALL 연산자 사용
SELECT
EMP_ID, EMP_NAME, JOB_NAME, SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '과장'
AND SALARY > ALL (SELECT
SALARY
FROM EMPLOYEE
JOIN JOB USING(JOB_CODE)
WHERE JOB_NAME = '차장');
3) 다중열 서브쿼리
: 서브 쿼리 SELECT 절에 나열된 컬럼이 여러 개일 때
3-1) 퇴사한 여직원과 같은 부서, 같은 직급에 해당하는 사원의 이름, 직급, 부서, 입사일 조회
(1) 퇴사한 여직원 조회
SELECT
EMP_NAME
, JOB_CODE
, DEPT_CODE
, HIRE_DATE
FROM EMPLOYEE
WHERE SUBSTR(EMP_NO, 8, 1) = '2'
AND ENT_YN = 'Y';
(2) 퇴사한 여직원과 같은 부서, 같은 직급인 사원 조회(단일열로 표현하면)
SELECT
EMP_NAME
, JOB_CODE
, DEPT_CODE
, HIRE_DATE
FROM EMPLOYEE
--같은 부서
WHERE DEPT_CODE =
(SELECT DEPT_CODE FROM EMPLOYEE WHERE SUBSTR(EMP_NO, 8, 1) = '2'
AND ENT_YN = 'Y')
--같은 직급
AND JOB_CODE = (SELECT JOB_CODE FROM EMPLOYEE WHERE SUBSTR(EMP_NO, 8, 1) = '2'
AND ENT_YN = 'Y');
(3) 다중열 서브쿼리로 변경
SELECT
EMP_NAME
, JOB_CODE
, DEPT_CODE
, HIRE_DATE
FROM EMPLOYEE
WHERE (DEPT_CODE , JOB_CODE)=
(SELECT DEPT_CODE, JOB_CODE FROM EMPLOYEE WHERE SUBSTR(EMP_NO, 8, 1) = '2'
AND ENT_YN = 'Y');
--> 이렇게 하면 오류 발생
--WHERE DEPT_CODE =
--(SELECT DEPT_CODE, JOB_CODE FROM EMPLOYEE WHERE SUBSTR(EMP_NO, 8, 1) = '2'
--AND ENT_YN = 'Y');
--> too many values 오류
4) 다중행 다중열 서브쿼리
: 서브쿼리 조회 결과 행의 개수와 열의 개수가 여러 개일때
4-1) 자기 직급의 평균 급여를 받고 있는 직원의 사번, 이름, 직급, 급여를 조회
단, 급여와 급여 평균은 십만원 단위로 계산한 TRUNC(컬럼명, -5)
(1) 직급별 평균 급여
SELECT
JOB_CODE
, TRUNC(AVG(SALARY), -5)
FROM EMPLOYEE
GROUP BY JOB_CODE;
4-2) 자기 직급의 평균 급여를 받고 있는 직원 조회
SELECT
EMP_ID
, EMP_NAME
, JOB_CODE
, SALARY
FROM EMPLOYEE
WHERE (JOB_CODE, SALARY) IN (SELECT
JOB_CODE
, TRUNC(AVG(SALARY), -5)
FROM EMPLOYEE
GROUP BY JOB_CODE);
'웹개발 수업 > SQL' 카테고리의 다른 글
[Day +40]서브쿼리, DDL (0) | 2021.08.19 |
---|---|
[Day +39 / SQL 과제]JOIN 10문제, SQL03_SELECT(Option) 8 ~ 15번 문제 (0) | 2021.08.17 |
[Day +38 / SQL]SQL 1차 시험 (0) | 2021.08.14 |
[Day +37 / SQL 과제]함수 SELECT(Funtion) 10~15번, SELECT(Option) 1~7번 (0) | 2021.08.12 |
[Day +37 / SQL]Group By & Having (0) | 2021.08.12 |