728x90
728x90

* 이 글은 제가 공부하기 위해 최대한 사실에 입각해 내용을 적으려고 하지만 일부 내용들이 정확하지 않을 수 있습니다.

   혹시나 잘못된 부분이 있으면 너그럽게 이해해 주시고 피드백 부탁드려요!


1. 조인의 개념

조인(Join)

• 조인의 개념

  – 하나의 SQL 명령문에 의해 여러 테이블에 저장된 데이터를 한 번에 조회할 수 있는 기능
  – 관계형 데이터베이스 분야의 표준
  – 두 개 이상의 테이블을 "결합" 한다는 의미

• 조인의 필요성

  – 조인을 사용하지 않는 일반적인 예

    • 학생 주소록을 출력하기 위해 학생들의 학번, 이름, 소속학과 이름을 검색
    • 학생에 대한 정보 검색하는 단계 필요
    • 학생 정보에서 소속학과 번호 정보를 추출하여 소속학과 이름을 검색하는 단계 필요

• 사용 예

– 학번이 10101인 학생의 이름과 소속 학과 이름을 출력하여라.

 

 

2. 칼럼 이름의 애매모호성, 테이블 별명, 조인 조건식

칼럼 이름의 애매모호성

• 칼럼 이름의 애매모호성 해결방법

  – 서로 다른 테이블에 있는 동일한 칼럼 이름을 연결한 경우 칼럼 이름 앞에 테이블 이름을 접두사로 사용

     테이블 이름과 칼럼 이름은 점(.)으로 구분

  – SQL 명령문에 대한 구문분석 시간(parsing time) 줄임

    • student.deptno와 department.deptno

 

테이블 별명

• 테이블 이름이 너무 긴 경우 사용

  – 테이블 이름을 대신하는 별명 사용 가능
  – FROM절에서 테이블 이름 다음에 공백을 두고 별명 정의
  – 테이블 별명 작성 규칙

    • 테이블의 별명은 30자까지 가능, 너무 길지 않게 작성
    • FROM 절에서 테이블 이름을 명시하고 공백을 둔 다음 테이블 별명지정
    • 하나의 SQL 명령문에서 테이블 이름과 별명을 혼용할 수 없다
    • 테이블의 별명은 해당 SQL 명령문내에서만 유효

 

• 사용 예

– 테이블 이름과 별명을 혼용하여 사용한 경우

– 테이블 별명을 정확하게 사용한 경우

 

AND 연산자를 사용한 검색 조건 추가

• 사용 예

– "전인하" 학생의 학번, 이름, 학과 이름 그리고 학과 위치를 출력하여라.

• 실습 예

– 몸무게가 80kg 이상인 학생의 학번, 이름, 체중, 학과 이름, 학과 위치를 출력하여라.

 

3. 조인의 종류

카티션 곱

• 카티션 곱

  – 두 개 이상의 테이블에 대해 연결 가능한 행을 모두 결합
  – WHERE 절에서 조인 조건절을 생략하거나 잘못 설정한 경우
  – 대용량 테이블에서 발생한 경우 SQL명령문의 처리속도 저하
  – 개발자가 시뮬레이션을 위한 대용량의 실험용 데이터를 생성하기 위해 의도적으로 사용 가능
  – 오라클 9i 이후 버전에서 FROM절에 CROSS JOIN 키워드 사용

 

• CROSS JOIN 사용법


• 사용 예

– 학생 테이블과 부서 테이블을 카테션 곱을 한 결과를 출력하여라.

EQUI JOIN

• 개념

  – 조인 대상 테이블에서 공통 칼럼을 "="(equal) 비교를 통해 같은 값을 가지는 행을 연결하여 결과를

     생성하는 조인 방법
  – SQL 명령문에서 가장 많이 사용하는 조인 방법
  – 조인 애트리뷰트(join attribute(속성))

• WHERE 절을 이용한 EQUI JOIN 사용법

  – FROM : 조인 대상 테이블을 기술한다. 테이블은 콤마(,)로 구분
  – WHERE : 조인 애트리뷰트와 "="연산자를 사용하여 조인 조건을 기술

• 사용 예

– 학생 테이블과 부서 테이블을 EQUI JOIN 하여 학번, 이름, 학과 번호, 소속 학과 이름, 학과 위치를

   출력하여라

EQUI JOIN – NATURAL JOIN

• 자연조인을 이용한 EQUI JOIN

  – 오라클 9i 버전부터 EQUI JOIN을 자연조인이라 명명
  – WHERE 절을 사용하지 않고 NATURAL JOIN 키워드 사용
  – 오라클에서 자동적으로 테이블의 모든 칼럼을 대상으로 공통 칼럼을 조사 후, 내부적으로 조인문 생성

• 사용법

  – 주의
     • 조인 애트리뷰트에 테이블 별명을 사용하면 오류가 발생

 

• 조인 애트리뷰트에서 테이블 별명을 사용한 경우

• 조인 애트리뷰트에서 테이블 별명을 사용하지 않은 경우

• 사용 예

– NATURAL JOIN을 이용하여 교수 번호, 이름, 학과 번호, 학과 이름을 출력하여라.

• 사용 예

– NATURAL JOIN을 이용하여 4학년 학생의 이름, 학과 번호, 학과 이름을 출력하여라.

EQUI JOIN – JOIN ~ USING

• JOIN ~ USING 절을 이용한 EQUI JOIN

  – USING절에 조인 대상 칼럼을 지정
  – 칼럼 이름은 조인 대상 테이블에서 동일한 이름으로 정의되어 있어야 함

• 사용법

  – 주의
    • 조인 애트리뷰트에 테이블 별명을 사용하면 오류가 발생

 

• 사용 예

– JOIN ~ USING 절을 이용하여 학번, 이름, 학과번호, 학과이름, 학과위치를 출력하여라.

• 실습 예

– EQUI JOIN의 3가지 방법을 이용하여 성이 "김"씨인 학생들의 이름, 학과이름, 학과위치를 출력하여라.

– WHERE 절을 사용한 방법

– NATURAL JOIN절을 사용한 방법

– JOIN~USING절을 사용한 방법

NON-EQUI JOIN

• NON-EQUI JOIN

  – "<", BETWEEN a AND b와 같이 "=" 조건이 아닌 연산자 사용

• 사용 예

– 교수 테이블과 급여 등급 테이블을 NON-EQUI JOIN 하여 교수별로 급여 등급을 출력하여라.

• 실습 예

– 101번 학과 교수의 교수번호, 이름, 급여, 급여 등급을 출력하여라.

OUTER JOIN

• 개요

  – EQUI JOIN의 조인 조건에서 양측 칼럼 값 중, 어느 하나라도 NULL 이면 "=" 비교 결과가 거짓이 되어

     NULL 값을 가진 행은 조인 결과로 출력불가

    • NULL에 대해서 어떠한 연산을 적용하더라도 연산 결과는 NULL

  – 일반적인 EQUI JOIN의 예 : 
    • 학생 테이블의 학과번호 칼럼과 부서 테이블의 부서번호 칼럼에 대한

      EQUI JOIN ( student.deptno = department.deptno ) 한 경우
      – 학생 테이블의 deptno 칼럼이 NULL 인 경우 해당 학생은 결과로 출력되지 못함
  – EQUI JOIN에서 양측 칼럼 값 중의 하나가 NULL이지만 조인 결과로 출력할 필요가 있는 경우

     OUTER JOIN 사용
  – OUTER JOIN의 예 : 
    • 학생 테이블과 교수 테이블을 EQUI JOIN 하여 학생의 지도 교수 이름 출력
    • 조건 : 지도 학생을 한 명도 배정받지 못한 교수 이름도 반드시 함께 출력

• (+) 기호를 사용한 OUTER JOIN

  – WHERE 절의 조인 조건에서 OUTER JOIN 연산자인 "(+)" 기호 사용
  – 조인 조건문에서 NULL 이 출력되는 테이블의 칼럼에 (+) 기호 추가

• 사용법

• 사용 예

– 학생 테이블과 교수 테이블을 조인하여 이름, 학년, 지도교수의 이름, 직급을 출력하여라. 단, 지도교수가 배정되지 않은 학생이름도 함께 출력하여라.

• OUTER JOIN의 제약사항

  – OUTER JOIN 연산자(+)는 NULL이 존재하는 칼럼 쪽에 표시
  – OUTER JOIN에서는 IN 연산자를 사용 불가
  – 다른 조건과 OR 연산자로 결합 불가

• 실습 예

– 학생 테이블과 교수 테이블을 조인하여 이름, 학년, 지도교수 이름, 직급을 출력하여라. 단, 지도학생을 배정받지 않은 교수 이름도 함께 출력하여라.

• OUTER JOIN ~ON 절을 사용한 OUTER JOIN

  – 오라클 9i 버전부터 OUTER JOIN 절 사용

• 사용법


• LEFT OUTER JOIN

  – FROM 절의 왼쪽에 위치한 테이블이 NULL을 가질 경우에 사용
  – WHERE절의 오른편에 "(+)" 기호를 추가한 것과 동일
  – 예 : 지도교수가 배정되지 않은 학생 명단을 출력하여라

• RIGHT OUTER JOIN

  – FROM 절의 오른쪽에 위치한 테이블이 NULL을 가질 경우, 사용
  – WHERE 절의 왼편"(+)" 기호를 추가한 것과 동일
  – 예
    • 지도학생이 배정되지 않은 교수 명단을 출력하여라

• FULL OUTER JOIN

  – LEFT OUTER JOIN과 RIGHT OUTER JOIN을 동시에 실행한 결과를 출력
  – 예
    • 지도교수가 없는 학생과 지도학생이 배정되지 않은 교수를 함께 출력하라.

 

• 실습 예

– 학생 테이블과 교수 테이블을 조인하여 학년, 이름, 지도교수 이름, 직급을 출력하여라. 단, 지도교수가 배정되지 않은 학생 명단과 지도 학생이 배정되지 않은 교수 명단도 함께 출력하여라.
– (+) 기호를 사용한 OUTER JOIN(1)

– (+) 기호를 사용한 OUTER JOIN(2)

– OUTER JOIN ~ON절을 사용한 OUTER JOIN

 

SELF JOIN

• 개요

  – 하나의 테이블 내에 있는 칼럼끼리 연결하는 조인이 필요한 경우 사용
  – 조인 대상 테이블이 자식 하나라는 것 외에는 EQUI JOIN과 동일

• WHERE 절을 사용한 SELF JOIN

  – 한 테이블에서 두 개의 칼럼을 연결하여 EQUI JOIN
  – FROM절에서 하나의 테이블에 테이블 별명지정
  – 예
    • 부서 테이블에서 WHERE 절을 사용하여 SELF JOIN을 처리

• JOIN ~ ON 절을 사용한 SELF JOIN

  – 오라클 9i에서 JOIN ~ ON 지원

• 사용법

• 사용 예

– 부서 테이블에서 SELF JOIN을 이용하여 부서 이름과 상위 부서의 이름을 출력하여라.
– WHERE절을 사용한 SELF JOIN방법

– JOIN~ON절을 사용한 SELF JOIN방법

• 사용 예

– 부서 번호가 201 이상인 부서 이름과 상위 부서의 이름을 출력하여라.
– WHERE절을 사용한 SELF JOIN방법

– JOIN~ON절을 사용한 SELF JOIN방법

CREATE TABLE EX_TYPE (
    C CHAR(10),
    V VARCHAR(10)
);

SELECT * FROM EX_TYPE;

INSERT INTO EX_TYPE VALUES('sql', 'sql');

SELECT * FROM EX_TYPE
WHERE C = 'sql     ';

SELECT * FROM EX_TYPE
WHERE V = 'sql';

-- 기본적으로 BOOLEAN으로 나옴(참, 거짓)
-- 공백을 없애야 참으로 나옴
-- 아니면 공백을 포함해서 비교
SELECT * FROM EX_TYPE
WHERE C = V || '       ';


-- 119페이지
-- 이 안에서는 칼럼이 안보임
DESC STUDENT;
-- ROWNUM 행번호(많이 쓰임)
SELECT STUDNO, ROWID, ROWNUM, SYSDATE FROM STUDENT;

-- 129페이지
SELECT 3*6*7*8 FROM STUDENT;
SELECT 3*6*7*8 FROM ROWNUM = 1;
SELECT 3*6*7*8 FROM DUAL;
SELECT SYSDATE FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'YY/MM/DD HH24:MI:SS') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'YY/MM/DD HH24:MI:SS') AS "시간" FROM DUAL;

-- F10 누르면 COST가 보임 비용이 적을 수록 효율적인 코드


-- 140페이지
-- 학생 테이블에서 1학년 학생만 검색하여 학번, 이름, 학과 번호를 출력하여라.
-- = 비교연산자, GRADE DATA TYPE 은 CHAR 타입
SELECT * FROM STUDENT;
SELECT * FROM STUDENT WHERE GRADE = '1';
SELECT STUDNO, NAME, DEPTNO FROM STUDENT WHERE GRADE = '1';
SELECT STUDNO, NAME, DEPTNO FROM STUDENT WHERE GRADE = 1;
-- 비용은 일종의 비교 지표
-- 밑에 줄은 TO_NUMBER =>  숫자로 타입이 바뀌는게 더 좋을 때가 있음
-- 항상 그런 것만은 아님.

-- 142페이지
-- 학생 테이블에서 몸무게가 70KG 이하인 학생만 검색하여 학번, 이름, 학년, 학과번호, 몸무게를 출력하여라.
SELECT * FROM STUDENT;
SELECT STUDNO, NAME, GRADE, DEPTNO, WEIGHT FROM STUDENT WHERE WEIGHT <= 70;
-- 부정연산자 사용
SELECT STUDNO, NAME, GRADE, DEPTNO, WEIGHT FROM STUDENT WHERE NOT WEIGHT <= 70;

-- 144페이지
-- 학생 테이블에서 1학년이면서 몸무게가 70KG 이상인 학생만 검색하여 이름, 학년, 몸무게, 학과번호를 출력하여라.
SELECT * FROM STUDENT WHERE GRADE = '1' AND WEIGHT >= 70;
SELECT NAME, GRADE, WEIGHT, DEPTNO FROM STUDENT WHERE GRADE = '1' AND WEIGHT >= 70;
SELECT NAME, GRADE, WEIGHT, DEPTNO 
FROM STUDENT 
WHERE GRADE = '1' AND WEIGHT >= 70;

SELECT 
    NAME, GRADE, WEIGHT, DEPTNO 
FROM 
    STUDENT 
WHERE 
    GRADE = '1' AND WEIGHT >= 70;
    
SELECT 
    NAME
    , GRADE
    , WEIGHT
    , DEPTNO
FROM 
    STUDENT 
WHERE 
    GRADE = '1' 
AND 
    WEIGHT >= 70;

-- 145페이지
-- 위와 동일한 테이블에서 1학년이거나 몸무게가 70KG 이상
SELECT NAME, GRADE, WEIGHT, DEPTNO FROM STUDENT WHERE GRADE = '1' OR WEIGHT >= 70;

-- 146페이지
-- 학생테이블에서 학과번호가 '101'이 아닌 학생의 학번과 이름과 학과번호를 출력해라
SELECT * FROM STUDENT WHERE NOT DEPTNO = '101';
SELECT STUDNO, NAME, DEPTNO FROM STUDENT WHERE NOT DEPTNO = '101';

-- 149페이지
-- BETWEEN 연산자를 사용하여 몸무게가 50KG에서 70KG 사이인 학생의 학번, 이름, 몸무게를 출력하여라.
SELECT * FROM STUDENT WHERE WEIGHT BETWEEN 50 AND 70;
SELECT STUDNO, NAME, WEIGHT FROM STUDENT WHERE WEIGHT BETWEEN 50 AND 70;
SELECT STUDNO, NAME, WEIGHT FROM STUDENT WHERE WEIGHT >= 50 AND WEIGHT <= 70;

-- 150페이지
-- 학생테이블에서 81년에서 83년도에 태어난 학생의 이름과 생년월일을 출력해라
SELECT NAME, BIRTHDATE FROM STUDENT WHERE BIRTHDATE BETWEEN '81/01/01' AND '83/12/31';
-- 날짜는 형변환을 해주는 것이 좋음
SELECT NAME, BIRTHDATE FROM STUDENT 
WHERE TO_CHAR(BIRTHDATE, 'YY') BETWEEN 81 AND 83;

-- 학생테이블에서 봄에 태어난 학생의 이름과 생년월일을 출력해라
-- 월정보만 뽑는다는게 쉽지는 않음(국가셋이 바뀔 수 도 있으니)
SELECT NAME, BIRTHDATE FROM STUDENT WHERE TO_CHAR(BIRTHDATE, 'MM') BETWEEN 03 AND 05;

-- 152페이지
-- IN 연산자를 사용하여 102번 학과와 201번 학과 학생의 이름, 학년, 학과번호를 출력하여라
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE DEPTNO IN (102,201);
-- 학과번호는 101, 102, 201 밖에 없으니
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE DEPTNO != 101;

-- IN을 써서 150페이지 예제 변환해보기
SELECT NAME, BIRTHDATE FROM STUDENT WHERE TO_CHAR(BIRTHDATE, 'YY') IN (81,82,83);
SELECT NAME, BIRTHDATE, TO_CHAR(BIRTHDATE, 'YY') FROM STUDENT WHERE TO_CHAR(BIRTHDATE, 'YY') IN (81,82,83);

-- 153페이지
-- LIKE ~와 같은 전치사 개념
-- 학생 테이블에서 성이 '김'씨인 학생의 이름, 학년, 학과 번호를 출력하여라.
-- %를 붙이면 뒤에 몇글자가 나오든지 상관없음 김O, 김OO
-- 김%, %김, %김%
-- 글자개수 제한 김__   _ : 글자갯수 한글이든 영어든 한글자씩
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE NAME LIKE '김%';
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE NAME LIKE '김__';

-- 학생테이블에서 이름이 3글자, 성은 '김'씨고 마지막 글자가 '영'으로 끝나는 학생의 이름, 학년, 학과번호를 출력하여라
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE NAME LIKE '김_영';

INSERT INTO STUDENT(STUDNO, NAME) VALUES(33333, '황보_정');
INSERT INTO STUDENT(STUDNO, NAME) VALUES(33334, '황보영');
SELECT STUDNO, NAME FROM STUDENT WHERE NAME LIKE '황보%';
SELECT STUDNO, NAME FROM STUDENT WHERE NAME LIKE '황보_%';
SELECT STUDNO, NAME FROM STUDENT WHERE NAME LIKE '황보\_%' ESCAPE '\';

-- 처음 켰던 테이블로 초기화됨
ROLLBACK;
-- ROLLBACK 은 삽입 조회 삭제 등에서만 적용?

-- 164 페이지
-- 교수 테이블에서 이름, 직급, 보직수당을 출력하여라
SELECT NAME, POSITION, COMM FROM PROFESSOR;

-- 166 페이지
-- 교수테이블에서 보직수당이 없는 교수의 이름, 직급, 보직수당을 출력하여라.
SELECT NAME, POSITION, COMM FROM PROFESSOR WHERE COMM IS NULL;

-- SELECT NAME, POSITION, COMM FROM PROFESSOR WHERE COMM = NULL; 이렇게 쓰면안됨
-- 이것은 NULL문자열 검색시 사용

-- 167페이지
-- 교수 테이블에서 급여에 보직수당을 더한 값은 sal_com이라는 별명으로 출력하여라
SELECT NAME, SAL, COMM, SAL+COMM sal_com FROM PROFESSOR;
-- NVL 함수(NULL을 0으로 바꿀수 있음)
-- NVL(NULL이 올수 있는 컬럼 | 값, 널일경우 대체값)
SELECT NAME, SAL, COMM, NVL(COMM, 0), SAL+COMM sal_com FROM PROFESSOR;
SELECT NAME, SAL, COMM, NVL(COMM, 0), SAL+NVL(COMM,0) sal_com FROM PROFESSOR;

-- 170페이지
-- 102번 학과의 학생 중에서 1학년 또는 4학년 학생의 이름, 학년, 학과 번호를 출력하여라.
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE DEPTNO = 102 AND GRADE = 1 OR GRADE = 4;
-- 위에 줄은 101번 학과인 학생도 나옴.(비교,논리연산자 때문에) AND부터 처리하고 4학년을 다 땡겨오기 때문
-- OR 연산자를 우선시 해주기 위해 묶어야함.
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE DEPTNO = 102 AND (GRADE = 1 OR GRADE = 4);
-- 아니면
SELECT NAME, GRADE, DEPTNO FROM STUDENT WHERE DEPTNO = 102 AND GRADE IN (1,4);

-- 175페이지
-- 1학년이면서 몸무게가 70KG이상인 학생의 집합(STUD_HEAVY)과 1학년 이면서 
-- 101번 학과에 소속된 학생(STUD_101)으로 구성된 두 개의 테이블 생성
CREATE TABLE STUD_HEAVY 
AS SELECT *
FROM STUDENT
WHERE WEIGHT >= 70 AND GRADE ='1';

CREATE TABLE STUD_101
AS SELECT *
FROM STUDENT
WHERE DEPTNO = 101 AND GRADE = '1';

-- 서재진이 겹침
SELECT * FROM STUD_HEAVY;
SELECT * FROM STUD_101;

-- UNION 합집합
SELECT * FROM STUD_HEAVY
UNION
SELECT * FROM STUD_101;

-- UNION ALL 중복 합집합
SELECT * FROM STUD_HEAVY
UNION ALL
SELECT * FROM STUD_101;

-- INTERSECT 교집합
SELECT * FROM STUD_HEAVY
INTERSECT
SELECT * FROM STUD_101;

-- MINUS 차집합(A-B)
SELECT * FROM STUD_HEAVY
MINUS
SELECT * FROM STUD_101;

-- MINUS 차집합(B-A)
SELECT * FROM STUD_101
MINUS
SELECT * FROM STUD_HEAVY;

-- 183 페이지
SELECT * FROM STUDENT ORDER BY 1;
SELECT * FROM STUDENT ORDER BY STUDNO;
SELECT * FROM STUDENT ORDER BY STUDNO DESC;

-- 185 페이지
-- 학생 테이블에서 이름을 가나다 순으로 정렬하여 이름, 학년, 전화번호를 출력하여라.
SELECT NAME, GRADE, TEL FROM STUDENT ORDER BY NAME;

-- 186 페이지
-- 학생 테이블에서 학년을 내림차순으로 정렬하여 이름, 학년, 전화번호를 출력하여라.
SELECT NAME, GRADE, TEL FROM STUDENT ORDER BY GRADE DESC;
-- SELECT절에 없어도 됨
SELECT NAME, GRADE, TEL FROM STUDENT ORDER BY HEIGHT DESC;

-- 200 페이지
-- 학생 테이블에서 학번이 '20101' 인 학생의 사용자 아이디를 소문자와 대문자로 변환하여 출력하여라.
SELECT USERID, LOWER(USERID), UPPER(USERID) FROM STUDENT WHERE STUDNO = 20101;

-- 202 페이지
-- 부서 테이블에서 부서 이름의 길이를 문자 수와 바이트 수로 각각 출력하여라
SELECT DNAME, LENGTH(DNAME), LENGTHB(DNAME) FROM DEPARTMENT;

-- 205 페이지
SELECT SUBSTR('ABCDE', 2, 3) FROM DUAL;
SELECT SUBSTR('ABCDE', -2, 3) FROM DUAL;
-- 없으면 없는대로 처리함
SELECT SUBSTR('ABCDE   ', 6, 3), SUBSTRB('가나다',2) FROM DUAL;
-- 나만 나옴
SELECT SUBSTR('ABCDE   ', 6, 3), SUBSTRB('가나다',2, 5) FROM DUAL;
SELECT SUBSTR('ABCDE   ', 6, 3), SUBSTRB('가나다',2, 6) FROM DUAL;
SELECT SUBSTR('ABCDE   ', 6, 3), SUBSTRB('가나다',2, 7) FROM DUAL;

-- 206 페이지
-- 학생 테이블에서 1학년 학생의 주민등록 번호에서 생년월일과 태어난 달을 추출하여 이름, 주민번호, 생년월일
-- 태어난 달을 출력하여라.
-- DECODE 주민번호 7번째 숫자로 남여 성별 판단
SELECT NAME, IDNUM, SUBSTR(IDNUM, 1, 6) AS "주민앞자리", SUBSTR(IDNUM, 3, 2) AS "월",
    DECODE(SUBSTR(IDNUM, 7,1), 1, '남자', '여자')
FROM STUDENT 
WHERE GRADE = '1';

-- 나머지연산
SELECT MOD(3,2) FROM DUAL;

-- 207 페이지
-- BC의 위치 찾기
SELECT INSTR('ABCDABCDABCD', 'BC') FROM DUAL;

SELECT INSTR('ABCDABCDABCD', 'BC', 5) FROM DUAL;
SELECT INSTR('ABCDABCDABCD', 'BC', -8) FROM DUAL;
SELECT INSTR('123456789ABC', 'BC', -1) FROM DUAL;
SELECT INSTR('ABCDABCDABCD', 'BC', -1, 2) FROM DUAL;

-- 208 페이지
-- 부서 테이블의 부서 이름 칼럼에서 '과'글자의 위치를 출력하여라.
SELECT DNAME, INSTR(DNAME,'과') FROM DEPARTMENT;

-- 211 페이지
-- 교수테이블에서 직급 칼럼의 왼쪽에 '*' 문자를 삽입하여 10바이트로 출력하고 
-- 교수 아이디 칼럼은 오른쪽에 '+'문자를 삽입하여 12바이트로 출력하여라.
SELECT POSITION, LPAD(POSITION, 10, '*'), USERID, RPAD(USERID, 12, '+') FROM PROFESSOR;

-- 아이디 길이에 따라 *표시
SELECT POSITION, LPAD(POSITION, 10, '*'), RPAD(USERID, 12, '+')
,RPAD(SUBSTR(USERID, 1, 3), 12, '*') SHOWN_ID
,RPAD(SUBSTR(USERID, 1, 3), LENGTH(USERID), '*') SHOWN_ID
FROM PROFESSOR;

-- 214 페이지
-- 부서 테이블에서 부서 이름의 마지막 글자인 '과'를 삭제하여 출력하여라
SELECT DNAME, RTRIM(DNAME, '과') FROM DEPARTMENT;

SELECT TRIM('      가나다라      **') FROM DUAL;

SELECT REPLACE('ABCDEABCDE', 'A', 'F') FROM DUAL;

-- 218 페이지
-- 교수 테이블에서 101학과 교수의 일급을 게산(월근무일은 22일)하여 소수점 첫째자리와
-- 셋째 자리에서 반올림 한 값과 소숫점 왼쪽 첫째 자리에서 반올림한 값을 출력하여라
SELECT NAME, SAL, SAL/22, ROUND(SAL/22), ROUND(SAL/22, 2), ROUND(SAL/22, -1) FROM PROFESSOR
WHERE DEPTNO = 101;

-- 220 페이지
-- 교수 테이블에서 101학과 교수의 일급을 계산(월 근무일은 22일)하여 소수점 첫째자리와
-- 셋째 자리에서 절삭한 값과 소숫점 왼쪽 첫째 자리에서 절삭한 값을 출력하여라
SELECT NAME, SAL, SAL/22, TRUNC(SAL/22), TRUNC(SAL/22, 2), TRUNC(SAL/22, -1)
FROM PROFESSOR WHERE DEPTNO = 101;

-- 222 페이지
-- 교수 테이블에서 101번 학과 교수의 급여를 보직수당으로 나눈 나머지를 계산하여 출력하여라
SELECT NAME, SAL, COMM, MOD(SAL,COMM) FROM PROFESSOR WHERE DEPTNO = 101;

-- 224 페이지
-- 19.7보다 큰 정수 중에서 가장 작은 정수와 12.345보다 작은 정수 중에서 가장 큰 정수를 출력하여라
SELECT CEIL(19.7), FLOOR(12.345) FROM DUAL;

-- 227 페이지
-- 교수 번호가 9908인 교수의 입사일을 기준으로 입사 30일 후와 60일 후의 날짜를 출력하여라
SELECT NAME, HIREDATE, HIREDATE+30, HIREDATE+60 FROM PROFESSOR WHERE PROFNO = 9908;

-- 229 페이지
SELECT SYSDATE FROM DUAL;

-- 수료날까지의 디데이 계산하기
SELECT TO_CHAR(SYSDATE, 'YY/MM/DD HH24:MI:SS')
    , TO_DATE('23/06/30 18:30:00', 'YY/MM/DD HH24:MI:SS')
    , ROUND(TO_DATE('23/06/30 18:30:00', 'YY/MM/DD HH24:MI:SS') - SYSDATE)
FROM DUAL;

-- 태어난 날로 부터 디데이 계산하기
SELECT TO_CHAR(SYSDATE, 'YY/MM/DD')
    , TO_DATE('1993/05/26', 'YY/MM/DD')
    , ROUND(SYSDATE - TO_DATE('1993/05/26', 'YY/MM/DD'))
FROM DUAL;

--23.02.01
----------------------------------------------------------------------------
-- 229 페이지
-- 시스템의 현재 날짜를 출력하여라.
SELECT SYSDATE FROM DUAL;

-- 231 페이지
-- 입사한지 360개월 미만인 교수의 교수번호, 입사일, 입사일로부터 현재일까지의 개월 수,
-- 입사일에서 6개월 후의 날짜를 출력하여라.
SELECT 
    PROFNO, HIREDATE, 
    MONTHS_BETWEEN(SYSDATE, HIREDATE), 
    ADD_MONTHS(HIREDATE, 6)
FROM PROFESSOR
WHERE MONTHS_BETWEEN(SYSDATE, HIREDATE) < 360;

-- 233페이지
-- 오늘이 속한 달의 마지막 날짜와 다가오는 일요일의 날짜를 출력하여라
-- KST 적용된 상태(KOREA STANDARD TIME), 다른 시간이면 한국어 안먹힘.
SELECT SYSDATE
    , LAST_DAY(SYSDATE)
    , NEXT_DAY(SYSDATE, '일요일')
FROM DUAL;

-- 같은 값(밑에것이 더 좋음)
SELECT SYSDATE
    , LAST_DAY(SYSDATE)
    , NEXT_DAY(SYSDATE, 1)
FROM DUAL;

-- 235페이지
-- 시간 정보를 생략한 경우, ROUND 함수와 TRUNC 함수의 결과를 비교한 예이다.
SELECT TO_CHAR(SYSDATE, 'YY/MM/DD HH24:MI:SS')
    , TO_CHAR(TRUNC(SYSDATE), 'YY/MM/DD HH24:MI:SS')  
    , TO_CHAR(ROUND(SYSDATE), 'YY/MM/DD HH24:MI:SS')
FROM DUAL;

SELECT TO_CHAR(SYSDATE + 3 / 24, 'YY/MM/DD HH24:MI:SS')
    , TO_CHAR(TRUNC(SYSDATE + 3 / 24), 'YY/MM/DD HH24:MI:SS')  
    , TO_CHAR(ROUND(SYSDATE + 3 / 24), 'YY/MM/DD HH24:MI:SS')
FROM DUAL;

-- 월기준 반올림할 때
SELECT ROUND(TO_DATE('231224', 'YYMMDD'), 'MM') FROM DUAL;

-- 236 페이지
-- 101번 학과 교수들의 입사일을 일, 월, 년을 기준으로 반올림하여 출력하여라.
SELECT TO_CHAR(HIREDATE, 'YY/MM/DD HH24:Mi:SS') A
    , TO_CHAR(ROUND(HIREDATE, 'DD'), 'YY/MM/DD HH24:Mi:SS') B
    , TO_CHAR(ROUND(HIREDATE, 'MM'), 'YY/MM/DD HH24:Mi:SS') C
    , TO_CHAR(ROUND(HIREDATE, 'YY'), 'YY/MM/DD HH24:Mi:SS') D
FROM PROFESSOR
WHERE DEPTNO =101;

-- 246 페이지
SELECT STUDNO, TO_CHAR(BIRTHDATE, 'YY.MM')
FROM STUDENT WHERE NAME = '전인하';

-- 247 페이지
SELECT NAME, GRADE, TO_CHAR(BIRTHDATE, 'DAY MONTH DD YYYY ')
FROM STUDENT WHERE DEPTNO = 102;

-- 249 페이지
-- 교수 테이블에서 101번 학과 교수의 이름과 입사일을 출력하여라.
SELECT NAME, TO_CHAR(HIREDATE, 'YYYY MONTH DD, PM HH24:MI;SS')
FROM PROFESSOR
WHERE DEPTNO = 101;

-- 251 페이지
SELECT NAME, TO_CHAR(HIREDATE, 'YYYY MONTH DDTH DDTHSP DAY DY, PM HH24:MI;SS')
    , TO_CHAR(SYSDATE, 'DDTH DDTHSP')
FROM PROFESSOR
WHERE DEPTNO = 101;

-- 253 페이지
-- 보직수당을 받는 교수들의 이름, 급여, 보직수당, 그리고 급여와 보직수당을 더한 값에
-- 12를 곱한 결과를 연봉으로 출력하여라.
SELECT NAME, SAL, COMM, TO_CHAR((SAL+COMM)*12, '9,999') "연봉" 
FROM PROFESSOR
WHERE COMM IS NOT NULL;

-- 저장 자리값 부족으로 ###이 뜸, 포매터가 무조건 더 크면 값 나옴
SELECT TO_CHAR(1234567890, '9,999') FROM DUAL;
SELECT TO_CHAR(1234567890, '9,999,999,999') FROM DUAL;

-- 257 페이지
-- 주민등록번호에서 생년월일을 추출하여 'YY/MM/DD' 형태로 출력하여라.
SELECT TO_CHAR(TO_DATE(SUBSTR(IDNUM,1,6), 'YYMMDD'), 'YY/MM/DD') A FROM STUDENT;

-- 260 페이지
-- 201번 학과 교수의 이름, 직급, 급여, 보직수당, 급여와 보직수당의 합계를 출력하여라.
-- 단, 보직수당이 NULL인 경우에는 보직수당을 0으로 계산한다.
SELECT NAME, POSITION, SAL, COMM, SAL+COMM, SAL+NVL(COMM, 0), NVL(SAL+COMM, SAL) 
FROM PROFESSOR WHERE DEPTNO = 201;

-- 261 페이지
SELECT NAME, POSITION, SAL, COMM
    , SAL+COMM
    , SAL+NVL(COMM, 0)
    , NVL(SAL+COMM, SAL) 
    , NVL2(COMM, SAL+COMM, SAL)
FROM PROFESSOR WHERE DEPTNO = 201;

-- 262 페이지
SELECT NAME, POSITION, SAL, COMM
    , NVL2(COMM, SAL+COMM, SAL) TOTAL
FROM PROFESSOR
WHERE DEPTNO = 102;

-- 270 페이지
SELECT NAME, DEPTNO
    , DECODE(DEPTNO, 101, '컴퓨터공학과', 102, '멀티미디어학과', 201, '전자공학과', '기계공학과')
FROM PROFESSOR;

-- 학생테이블에서 생년월일을 기준으로 탄생월을 추출하여 이름, 탄생월, 탄생계절을 조회하시오.
SELECT NAME AS 이름, 
    TO_CHAR(TO_DATE(SUBSTR(IDNUM,3,2), 'MM'), 'MM') "탄생월"
    , SUBSTR(IDNUM,3,2) AS 탄생월
    , DECODE(SUBSTR(IDNUM,3,2), 03, '봄', 04, '봄', 05, '봄', 06, '여름', 07, '여름', 08, '여름', 09, '가을', 10,' 가을', 11, '가을', '겨울')
    AS 탄생계절
FROM STUDENT;

DESC STUDENT;
SELECT 
    TO_CHAR(BIRTHDATE, 'MM') A
    , TO_CHAR(BIRTHDATE, 'MM') / 3 B
    , TRUNC(TO_CHAR(BIRTHDATE, 'MM') / 3) C
    , DECODE(TRUNC(TO_CHAR(BIRTHDATE, 'MM') / 3), 1, '봄', 2, '여름', 3, '가을', '겨울') "계절"
    , BIRTHDATE
    , ADD_MONTHS(BIRTHDATE, -2) "2달땡기기"
    , TO_CHAR(ADD_MONTHS(BIRTHDATE, -2), 'Q') 다른방법
    , DECODE(TO_CHAR(ADD_MONTHS(BIRTHDATE, -2), 'Q'), 1, '봄', 2, '여름', 3, '가을', '겨울') "계절"
FROM STUDENT;

-- 272페이지
SELECT 
    NAME, DEPTNO, SAL, 
    DECODE(DEPTNO, 101, SAL*0.1, 102, SAL*2, 201, SAL*0.3, 0),
    CASE DEPTNO 
        WHEN 101 THEN SAL*0.1
        WHEN 102 THEN SAL*0.2
        WHEN 201 THEN SAL*0.3
        ELSE 0
    END A,
    CASE
        WHEN DEPTNO = 101 THEN SAL*.1
        WHEN DEPTNO = 102 THEN SAL*.2
        WHEN DEPTNO = 201 THEN SAL*.3
        ELSE 0
    END B
FROM PROFESSOR;


-- NUMBER 씌워서 해보기
SELECT
    NAME, BIRTHDATE,
    CASE TO_CHAR(BIRTHDATE, 'MM')
        WHEN '1' THEN '봄'
        WHEN '2' THEN '여름'
        WHEN '3' THEN '가을'
        ELSE '겨울'
    END A
FROM STUDENT;

SELECT
    NAME, BIRTHDATE,
    CASE 
        WHEN TO_CHAR(BIRTHDATE, 'MM') BETWEEN 3 AND 5  THEN '봄'
        WHEN TO_CHAR(BIRTHDATE, 'MM') IN(6,7,8)  THEN '여름'
        WHEN TO_CHAR(BIRTHDATE, 'MM') >= 9 AND TO_CHAR(BIRTHDATE, 'MM') <= 11 THEN '가을'
        ELSE '겨울'
    END J
FROM STUDENT;
        
SELECT 
    CASE 
        WHEN TO_CHAR(BIRTHDATE, 'MM') BETWEEN 3 AND 5  THEN '봄'
        WHEN TO_CHAR(BIRTHDATE, 'MM') IN(6,7,8)  THEN '여름'
        WHEN TO_CHAR(BIRTHDATE, 'MM') >= 9 AND TO_CHAR(BIRTHDATE, 'MM') <= 11 THEN '가을'
        ELSE '겨울'
    END J
FROM(
SELECT STUDENT.*, TO_CHAR(BIRTHDATE, 'MM') MON FROM STUDENT
);

SELECT 
    CASE 
        WHEN MON BETWEEN 3 AND 5  THEN '봄'
        WHEN MON IN(6,7,8)  THEN '여름'
        WHEN MON >= 9 AND TO_CHAR(BIRTHDATE, 'MM') <= 11 THEN '가을'
        ELSE '겨울'
    END J
FROM(
SELECT STUDENT.*, TO_CHAR(BIRTHDATE, 'MM') MON FROM STUDENT
);



-- 23-02-02
-------------------------------------------------------------------------------
-- 284페이지
-- 101번 학과 교수 중에서 보직수당을 받는 교수의 수를 출력하여라
SELECT COUNT(*)
FROM PROFESSOR
WHERE DEPTNO = 101;

SELECT COUNT(COMM)
FROM PROFESSOR
WHERE DEPTNO = 101;

SELECT *
FROM PROFESSOR
WHERE DEPTNO = 101 AND COMM IS NOT NULL;

-- 집계함수는 일반컬럼이랑 같이 사용할 수 없음

SELECT COUNT(*), SUM(COMM), AVG(COMM), MAX(COMM), MIN(COMM)
FROM PROFESSOR
WHERE DEPTNO = 101 AND COMM IS NOT NULL;

-- 285 페이지
-- 101번 학과 학생들의 몸무게 평균과 합계를 출력하여라
SELECT AVG(WEIGHT), SUM(WEIGHT) 
FROM STUDENT
WHERE DEPTNO = 101;

-- 286 페이지
-- 102번 학과 학생 중에서 최대 키와 최소 키를 출력하여라.
SELECT MAX(HEIGHT), MIN(HEIGHT)
FROM STUDENT
WHERE DEPTNO = 102;

-- 287 페이지
-- 교수 테이블에서 급여의 표준편차와 분산을 출력하여라.


-- 291 페이지
-- 교수 테이블에서 학과별로 교수 수와 보직수당을 받는 교수 수를 출력하여라
SELECT DEPTNO, COUNT(COMM), COUNT(DEPTNO)
FROM PROFESSOR
GROUP BY DEPTNO
ORDER BY 1;

-- 293 페이지
-- 학과별로 소속 교수들의 평균급여, 최소 급여, 최대 급여를 출력하여라
SELECT DEPTNO, POSITION, AVG(SAL), MIN(SAL), MAX(SAL)
FROM PROFESSOR
GROUP BY DEPTNO, POSITION;

-- 294 페이지
-- 전체 학생을 소속 학과별로 나누고, 같은 학과 학생은 다시 학년별로 그룹핑하여
-- 학과와 학년별로 인원수, 평균 몸무게를 출력하여라, 단, 평균 몸무게는 소수점 이하
-- 첫번째 자리에서 반올림 한다.
SELECT DEPTNO, GRADE, COUNT(*), ROUND(AVG(WEIGHT))
FROM STUDENT
GROUP BY DEPTNO, GRADE
ORDER BY 1,2;
-- 201번 학과가 학년이 3,4학년이 없어서 2개만 나옴

-- 297 페이지
-- 소속 학과별로 교수 급여 합계와 모든 학과 교수들의 급여 합계를 출력하여라
SELECT DEPTNO, SUM(SAL)
FROM PROFESSOR
--GROUP BY ROLLUP(DEPTNO);
GROUP BY DEPTNO;


SELECT SUM(SAL)
FROM PROFESSOR;

-- UNION을 쓰기 위해서는 두 컬럼이 갯수가 같아야함.
SELECT DEPTNO, SUM(SAL)
FROM PROFESSOR
--GROUP BY ROLLUP(DEPTNO);
GROUP BY DEPTNO
UNION
SELECT NULL, SUM(SAL)
FROM PROFESSOR;

-- COST 비용가 낮아서 결국 비교하게 됨(f10키)
SELECT DEPTNO, SUM(SAL)
FROM PROFESSOR
GROUP BY ROLLUP(DEPTNO);

-- 298 페이지
-- ROLLUP 연산자를 이용하여 학과 및 직급별 교수수, 학과별 교수수, 전체 교수수를 출력하여라
SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY DEPTNO, POSITION
ORDER BY DEPTNO, POSITION;

SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY ROLLUP(DEPTNO, POSITION)
ORDER BY DEPTNO, POSITION;
-- 아우터 조인을 쓰면 합계 NULL에 대한 값을 넣을 수 있음.

SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY ROLLUP(POSITION, DEPTNO)
ORDER BY DEPTNO, POSITION;

-- UNION 쓴것
SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY ROLLUP(DEPTNO, POSITION)
UNION
SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY ROLLUP(POSITION, DEPTNO);

-- CUBE 쓴것
SELECT DEPTNO, POSITION, COUNT(*)
FROM PROFESSOR
GROUP BY CUBE(POSITION, DEPTNO)
ORDER BY DEPTNO, POSITION;

-- 299 페이지
-- CUBE 연산자를 이용하여 학과 및 직급별 교수 수, 학과별 교수 수, 전체 교수 수를 출력하여라.


-- 300 페이지
SELECT DEPTNO, POSITION, GROUPING(DEPTNO), GROUPING(POSITION), COUNT(*)
FROM PROFESSOR
GROUP BY CUBE(POSITION, DEPTNO)
ORDER BY DEPTNO, POSITION;
-- NULL이 있는 것들이 결과값 1이 나옴

-- 301 페이지
-- 전체 학생을 학과와 학년별로 그룹화한 후, 학과와 학년별 그룹 인원 수, 학과별
-- 인원 수, 각 그룹 조합에서 학과와 학년 칼럼이 사용되었는지 여부를 출력하여라.

-- 309 페이지
-- 학생 수가 4명 이상인 학년에 대해서 학년, 학생 수 , 평균 키, 평균 몸무게를 출력하여라.
-- 단, 평균 키와 평균 몸무게는 소수점 첫번째 자리에서 반올리하고, 출력순서는 평균 키가
-- 높은 순부터 내림차순으로 출력하여라.
SELECT GRADE, COUNT(*), ROUND(AVG(HEIGHT)), ROUND(AVG(WEIGHT))
FROM STUDENT
GROUP BY GRADE
HAVING COUNT(*) >=4
ORDER BY AVG(HEIGHT) DESC;

SELECT GRADE, COUNT(*), ROUND(AVG(HEIGHT)), ROUND(AVG(WEIGHT))
FROM STUDENT
WHERE PROFNO IS NOT NULL
GROUP BY GRADE
HAVING COUNT(*) >=4
ORDER BY 3 DESC;

SELECT GRADE, COUNT(*), ROUND(AVG(HEIGHT)), ROUND(AVG(WEIGHT))
FROM STUDENT
--WHERE PROFNO IS NOT NULL
GROUP BY GRADE
--HAVING COUNT(*) >=4
ORDER BY 3 DESC;

-- 절별 실행순서 확인하기
SELECT GRADE1, COUNT(*), ROUND(AVG(HEIGHT)), ROUND(AVG(WEIGHT))
FROM STUDENT1
WHERE PROFNO1 IS NOT NULL
GROUP BY GRADE1
HAVING COUNT(STUDENT1) >=4
ORDER BY ROUND(AVG(HEIGHT1)) DESC;

--table or view does not exist
-- FROM 이 1번

SELECT GRADE, COUNT(*), ROUND(AVG(HEIGHT)), ROUND(AVG(WEIGHT))
FROM STUDENT
WHERE PROFNO IS NOT NULL
GROUP BY GRADE
HAVING COUNT(*) >=4
ORDER BY ROUND(AVG(HEIGHT)) DESC;

-- FROM > WHERE > GROUP BY > HAVING > SELECT > ORDER BY

-- 마트 > 식품층 > 바구니, 카트 > 어떻게 담을지 > 물품선별작업 > 계산 순서

-- 311 페이지
SELECT DEPTNO, AVG(SAL)
FROM PROFESSOR
GROUP BY DEPTNO
HAVING DEPTNO > 102;

SELECT DEPTNO, AVG(SAL)
FROM PROFESSOR
WHERE DEPTNO > 102
GROUP BY DEPTNO;

-- 319페이지
-- 학생의 학번, 학과번호, 학과 이름을 조회
SELECT *
FROM STUDENT, DEPARTMENT;
-- 16 * 7 이어서 112개 행이 나옴
-- 학생한명(전인하) 기준 당 7개의 부서랑 연결

SELECT STUDNO, NAME, STUDENT.DEPTNO, DNAME
FROM STUDENT, DEPARTMENT
WHERE STUDENT.DEPTNO = DEPARTMENT.DEPTNO
ORDER BY 1;

-- 오류발생 DEPTNO가 같아서.
SELECT STUDNO, NAME, DEPTNO, DNAME
FROM STUDENT, DEPARTMENT
WHERE STUDENT.DEPTNO = DEPARTMENT.DEPTNO
ORDER BY 1;

-- 324 페이지
-- 별칭 붙히기
SELECT STUDNO, NAME, S.DEPTNO, DNAME
FROM STUDENT S, DEPARTMENT D
WHERE S.DEPTNO = D.DEPTNO
-- 326 페이지
AND NAME = '전인하';

-- 전인하라는 이름을 가지는 학생의 학번, 이름, 담당교수번호, 담당교수 이름을 조회하시오.
SELECT STUDNO, S.NAME, P.NAME, P.PROFNO
FROM STUDENT S, PROFESSOR P
WHERE S.PROFNO = P.PROFNO
AND S.NAME = '전인하';

SELECT * 
FROM PROFESSOR, STUDENT;

SELECT *
FROM STUDENT S, DEPARTMENT D
WHERE S.DEPTNO = D.DEPTNO;

-- 안시조인? 자연조인?
SELECT *
FROM STUDENT
NATURAL JOIN DEPARTMENT;

-- INNER가 생략되어 있는 상태
SELECT *
FROM STUDENT
NATURAL INNER JOIN DEPARTMENT;

SELECT STUDNO, NAME, DEPTNO, DNAME
FROM STUDENT
NATURAL JOIN DEPARTMENT;


-- 23.02.03
-------------------------------------------------------------------------------
-- ANSI JOIN
SELECT STUDNO, NAME, DEPTNO, DNAME
FROM STUDENT
JOIN DEPARTMENT USING(DEPTNO);
-- using, on : ANSI JOIN을 사용하려면
-- 컬럼 이름이 다를 경우는 ON 조건 사용
SELECT STUDNO, NAME, STUDENT.DEPTNO, DNAME
FROM STUDENT
JOIN DEPARTMENT ON STUDENT.DEPTNO = DEPARTMENT.DEPTNO
WHERE NAME = '전인하';


-- 329페이지
SELECT STUDNO, NAME, DNAME
FROM STUDENT
CROSS JOIN DEPARTMENT;

-- 333 페이지
-- 학생 테이블과 부서 테이블을 EQUI  JOIN하여 학번, 이름, 학과번호, 소속학과 이름,학과 위치를 출력하여라.
SELECT S.STUDNO, S.NAME, S.DEPTNO, D.DNAME, D.LOC
FROM STUDENT S, DEPARTMENT D
WHERE S.DEPTNO = D.DEPTNO;

-- 뷰라고 불림
WITH A AS ( 
    SELECT 1 A, 2 B FROM DUAL
    UNION
    SELECT 3, 4 FROM DUAL
)
SELECT * 
FROM A
CROSS JOIN A
CROSS JOIN A
CROSS JOIN A;

-- 날짜, 로우넘=행(의사컬럼), 다량의 행 테이블있으면 달력 뽑을 수 있음
-- 데이터 디셕너리
SELECT * FROM ALL_OBJECTS;
-- ALL, USER 3가지 있음
SELECT * FROM DICT;
SELECT COUNT(*) FROM DICT;
SELECT ROWNUM FROM DICT WHERE ROWNUM <=31;

-- 334 페이지
-- 공통컬럼은 반드시 별칭을 붙이면 안됨
SELECT S.STUDNO, DEPTNO
--SELECT S.STUDNO, S.DEPTNO
FROM STUDENT S
NATURAL JOIN DEPARTMENT D;

-- 336 페이지
-- NATURAL JOIN을 이용하교 교수 번호, 이름, 학과 번호, 학과 이름을 출력하여라.
SELECT P.PROFNO, NAME, DEPTNO, D.DNAME
FROM PROFESSOR P
NATURAL JOIN DEPARTMENT D;

-- 337페이지

-- 339 페이지
-- JOIN ~ USING 절을 이용하여 학번, 이름, 학과 번호, 학과 이름, 학과 위치를 출력하여라.
SELECT STUDNO, NAME, DEPTNO, DNAME, LOC
FROM STUDENT
JOIN DEPARTMENT USING(DEPTNO);

-- 340 페이지
-- EQUI JOIN
SELECT *
FROM STUDENT
JOIN DEPARTMENT USING(DEPTNO)
WHERE NAME LIKE '김%';

SELECT NAME, DNAME, LOC
FROM STUDENT
JOIN DEPARTMENT USING(DEPTNO)
WHERE NAME LIKE '김%';

SELECT NAME, DNAME, LOC
FROM STUDENT S
JOIN DEPARTMENT D
ON S.DEPTNO = D.DEPTNO
WHERE NAME LIKE '김%';

SELECT NAME, DNAME, LOC
FROM STUDENT
NATURAL JOIN DEPARTMENT
WHERE NAME LIKE '김%';

SELECT NAME, DNAME, LOC
FROM STUDENT S, DEPARTMENT D
WHERE NAME LIKE '김%' AND S.DEPTNO = D.DEPTNO;

-- 341 페이지
SELECT * 
FROM SALGRADE;

SELECT * FROM PROFESSOR;

-- NON-EQUI JOIN
--SELECT S.HISAL, P.*
SELECT NAME, SAL, GRADE
FROM PROFESSOR P
JOIN SALGRADE S ON P.SAL BETWEEN LOSAL AND HISAL;

SELECT DISTINCT PROFNO
FROM PROFESSOR P 
JOIN STUDENT S USING(PROFNO);

-- 345 페이지
-- inner join
SELECT STUDNO, S.NAME, PROFNO, P.NAME
FROM STUDENT S
JOIN PROFESSOR P USING(PROFNO);

-- outer join , left join
SELECT STUDNO, S.NAME, PROFNO, P.NAME
FROM STUDENT S
LEFT JOIN PROFESSOR P USING(PROFNO);

-- 삭제하는법 -------------------------------
DELETE STUDENT WHERE STUDIO IN (33333,33334);
COMMIT;
---------------------------------------------

-- 아우터 조인 몰라도 union으로도 표현할 수 는 있음
-- 다만 가독성 등 고려했을 때 아우터 조인 사용
-- 
-- full join
SELECT STUDNO, S.NAME, PROFNO, P.NAME
FROM STUDENT S
FULL JOIN PROFESSOR P USING(PROFNO);

SELECT STUDNO, S.NAME, PROFNO, P.NAME
FROM STUDENT S
FULL JOIN PROFESSOR P USING(PROFNO)
ORDER BY 1, 3;

SELECT STUDNO, S.NAME, PROFNO, P.NAME
FROM STUDENT S
LEFT OUTER JOIN PROFESSOR P USING(PROFNO);

SELECT *
FROM PROFESSOR P, STUDENT S
WHERE P.PROFNO = S.PROFNO(+);
--WHERE P.PROFNO(+) = S.PROFNO;

-- 이건 안됨
SELECT *
FROM PROFESSOR P, STUDENT S
WHERE P.PROFNO(+) = S.PROFNO(+);

-- 356 페이지
SELECT * 
FROM DEPARTMENT D
JOIN DEPARTMENT D1 
ON D.DEPTNO = D1.DEPTNO;

-- 내부조인으로 되어있기 때문에 공과대학의 콜리지가 NULL이라서 6개만 나옴
SELECT D1.DNAME || '의 상위 학과는 ' || D2.DNAME
FROM DEPARTMENT D1,DEPARTMENT D2
WHERE D1.COLLEGE = D2.DEPTNO;

SELECT D1.DNAME || '의 상위 학과는 ' || D2.DNAME
FROM DEPARTMENT D1,DEPARTMENT D2
WHERE D1.COLLEGE = D2.DEPTNO(+);

SELECT D1.DNAME || '의 상위 학과는 ' || NVL(D2.DNAME, '없습니다')
FROM DEPARTMENT D1,DEPARTMENT D2
WHERE D1.COLLEGE = D2.DEPTNO(+);

SELECT D1.DNAME || '의 상위 학과는 ' || NVL(D2.DNAME, '없습니다')
FROM DEPARTMENT D1 LEFT JOIN DEPARTMENT D2
ON D1.COLLEGE = D2.DEPTNO;


-- 368 페이지
-- 사용자 아이디가 'JUN123'인
SELECT * 
FROM STUDENT 
WHERE GRADE = (
    SELECT GRADE
    FROM STUDENT
    WHERE USERID = 'jun123'
);

SELECT STUDNO, NAME, GRADE 
FROM STUDENT 
WHERE GRADE = (
    SELECT GRADE
    FROM STUDENT
    WHERE USERID = 'jun123'
);
    
SELECT STUDNO, NAME, GRADE 
FROM STUDENT 
WHERE GRADE = '4';

-- SELECT STUDNO, NAME, DEPTNO, (?) DNAME
SELECT STUDNO, NAME, DEPTNO, (SELECT DNAME FROM DEPARTMENT WHERE DEPARTMENT.DEPTNO = STUDENT.DEPTNO) DNAME
FROM STUDENT;

-- COST 2
SELECT STUDNO, NAME, DEPTNO, 
    (SELECT DNAME FROM DEPARTMENT D WHERE D.DEPTNO = S.DEPTNO) DNAME
FROM STUDENT S;

-- COST 5
SELECT STUDNO, NAME, DEPTNO, DNAME
FROM STUDENT NATURAL JOIN DEPARTMENT;

-- 369 페이지
-- 101번 학과 학생들의 평균 몸무게보다 몸무게가 적은 학생의 이름, 학과번호, 몸무게를 출력하여라.
SELECT NAME, DEPTNO, WEIGHT
FROM STUDENT
WHERE WEIGHT < (SELECT AVG(WEIGHT)
    FROM STUDENT
    WHERE DEPTNO = 101
);

-- 370 페이지
-- 20101번 학생과 학년이 같고, 키는 20101번 학생보다 큰 학생의 이름, 학년, 키를 출력하여라
SELECT NAME, GRADE, HEIGHT
FROM STUDENT
WHERE GRADE = (  -- 1 GRADE
    SELECT GRADE
    FROM STUDENT
    WHERE STUDNO = 20101
)
AND
    HEIGHT > ( -- 172CM
    SELECT HEIGHT
    FROM STUDENT
    WHERE STUDNO = 20101
);


-- 373 페이지
-- 정보 미디어학부
SELECT STUDNO, NAME, DEPTNO
FROM STUDENT
WHERE DEPTNO IN (
    SELECT DEPTNO FROM DEPARTMENT
    WHERE COLLEGE = 100
);

-- 동일한 해법
SELECT STUDNO, NAME, DEPTNO
FROM STUDENT
WHERE DEPTNO IN (101, 102);

-- 해당사항이 없으면 결과값이 나오지 않는다.
SELECT STUDNO, NAME, DEPTNO
FROM STUDENT
WHERE DEPTNO IN (
    SELECT DEPTNO FROM DEPARTMENT
    WHERE COLLEGE = 300
);

-- 374
SELECT STUDNO, NAME, HEIGHT
FROM STUDENT
WHERE HEIGHT > ANY (
    SELECT HEIGHT
    FROM STUDENT
    WHERE GRADE = '4'
);

-- ANY와 MIN을 결합하면 안됨
SELECT STUDNO, NAME, HEIGHT
FROM STUDENT
WHERE HEIGHT >  (
    SELECT MIN(HEIGHT)
    FROM STUDENT
    WHERE GRADE = '4'
);

SELECT STUDNO, NAME, HEIGHT
FROM STUDENT
WHERE HEIGHT <  (
    SELECT MAX(HEIGHT)
    FROM STUDENT
    WHERE GRADE = '4'
);

-- 376 페이지
SELECT STUDNO, NAME, HEIGHT
FROM STUDENT
WHERE HEIGHT >  (
    SELECT MAX(HEIGHT)
    FROM STUDENT
    WHERE GRADE = '4'
);

-- 377 페이지
SELECT STUDNO, NAME, HEIGHT
FROM STUDENT
WHERE HEIGHT > ALL (
    SELECT HEIGHT
    FROM STUDENT
    WHERE GRADE = '4'
);

-- 379 페이지
SELECT * FROM STUDENT WHERE 1=0;
-- 왜 굳이 볼까?
-- 테이블 구조만 복사해서 생성할때 서브쿼리로 이용하기 위해
SELECT * FROM USER_TABLES;
SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'STUDENT';
-- 테이블 구조 복사
-- CREATE TABLE STU2 AS SELECT * FROM STUDENT WHERE 1=0;

-- 380 페이지
-- 보직수당을 받는 교수가
SELECT PROFNO, NAME, SAL, COMM, SAL+NVL(COMM, 0)
FROM PROFESSOR 
WHERE EXISTS (SELECT *
FROM PROFESSOR
WHERE COMM IS NOT NULL);

-- 385 페이지
SELECT * FROM STUDENT
WHERE (GRADE, WEIGHT) IN (
    SELECT GRADE, MIN(WEIGHT)
    FROM STUDENT
    GROUP BY GRADE
);

SELECT NAME, GRADE, WEIGHT FROM STUDENT
WHERE GRADE IN (
    SELECT GRADE
    FROM STUDENT
    GROUP BY GRADE
)
AND WEIGHT IN (
    SELECT MIN(WEIGHT)
    FROM STUDENT
    GROUP BY GRADE
)
ORDER BY 2, 3;

SELECT NAME, HEIGHT, DEPTNO FROM STUDENT S1
WHERE HEIGHT < (
SELECT AVG(HEIGHT)
FROM STUDENT S2
WHERE S2.DEPTNO = S1.DEPTNO);

 

728x90
300x250