728x90

 

CREATE

 

데이터타입 : 문자, 숫자, 날짜

제약조건

NOT NULL

UNIQUE

PRIMARY KEY

FOREIGN KEY

CEHCK

 

 

------------------------------------------------------------------------------
-------------------------------DDL--------------------------------------------
------------------------------------------------------------------------------
/*
CREATE

1.테이블 만들기

테이블 = 객체

CREATE TABLE

테이블 DB의 가장 기본적인 객체
테이블 생성은 객체생성

*/
CREATE TABLE MEMBER(
    MEMBER_ID VARCHAR2(20),  -- 컬럼명 컬럼의 // 데이터타입(데이터크기)
    MEMBER_PWD VARCHAR2(20), -- MEMBER_PWD  // VARCHAR2(20)
    MEMBER_NAME VARCHAR2(20)
);

/*
데이터 타입
문자 : CHAR(크기[바이트/문자]), VARCHAR2(크기[바이트/문자]), NVARCHAR, LOB
    CHAR : 고정 문자열 자료형 (최대 2000byte)
    VARCHAR2 : 가변 문자열 자료형 (최대 40000byte)
    ex. CHAR(10) : 바이트 / CHAR(10char) : 문자
            한글 3글자          한글 10글자
    ex. CHAR(10char)                 VS   VARCHAR2(10) 
    안녕하세요_ _ _ _ _(공백5자리가 유지) //  안녕하세요(공백 유지X)
    → 위의 공백 유지 여부가 CHAR와 VARCHAR2의 차이


    NVARCHAR : 문자 개수 자체를 길이로 계산하는 자료형 --> 다양한 언어가 들어가는 유니코드에 적합
    LOB : CLOB/BLOB 두종류가 있고, 기가까지 저장가능. CLOB을 좀 더 많이 쓴다

숫자 : NUMBER[(P,S)]
크기(길이)를 집어 넣을 수 있는 인자가 있다
    NUMBER : 최고 40자리
    
    NUMBER(크기) : 길이 지정 가능
                P : 최대 자리수 / S : 소수점 자리수
                EX).NUMBER(4,3) --> 최대 4자리수, 소수점 3자리까지 허용
    
날짜 - DATE : 날짜와 시간을 저장하는 날짜형 데이터 타입
    - TIMESTAMP : DATE형 의 확장된 형태로 밀리초 단위까지 표현 가능한 데이터 타입

*실무가면 툴인 developer프로그램보다 cmd창을 더 많이 이용할 것

*/


-- 컬럼에 주석달기
COMMENT ON COLUMN MEMBER.MEMBER_ID IS '회원 아이디'; 
-- 코드 의미 : MEMEBER테이블 MEMBER_ID라는 컬럼에 '회원 아이디'라고 주석을 달겠다
COMMENT ON COLUMN MEMBER.MEMBER_PWD IS '회원 비밀번호'; 
COMMENT ON COLUMN MEMBER.MEMBER_NAME IS '회원 이름'; 
COMMENT ON COLUMN MEMBER.MEMBER_NAME IS '회원 네임'; -- 덮어씀

COMMENT ON COLUMN MEMBER.MEMBER_NAME IS '회원 이름';

-- CMD에서 작성한 테이블 확인 방법
-- 방법1
SELECT * FROM USER_TABLES; -- 사용자가 작성한 테이블을 확인하는 뷰
-- 방법2
SELECT *
FROM USER_TAB_COLUMNS
WHERE TABLE_NAME = 'MEMBER';
-- 방법3
DESC MEMBER;

SELECT * FROM USER_TABLES;
DESC USER_CONSTRAINTS;


------------------------------------------------------------------------------
----------------------------------제약조건(CONSTRAINTS)------------------------
------------------------------------------------------------------------------



/*

<제약조건(CONSTRAINTS)>
테이블 작성 시, 각 컬럼마다 값 기록에 대한 제약 조건 설정 가능
    ex) null 값 받을 수 있는지 여부, 주민번호 Number 타입만 받도록 설정
    
사용목적 : 데이터 무결성 보장
    데이터 무결성이란?
    데이터 정확성, 일관성, 유효성이 유지되는 것


*/

DESC USER_CONSTRAINTS; -- 사용자가 작성한 제약조건 확인 뷰

SELECT * FROM USER_CONSTRAINTS;

/*
-- 제약조건 종류
NOT NULL : 데이터에 NULL 허용 X
UNIQUE : 중복된 값 허용 X
PRIMARY KEY : NOT NULL + UNIQUE ← 고유 식별자로 사용 : 각 컬럼을 식별할 수 있는 고유 식별자
FOREIGN KEY : 외부 테이블에서 참조해 온 컬럼값이 존재하면 허용
CHECK :  데이터 값의 범위나 조건을 지정해 설정한 값만 허용

한 컬럼에 제약조건 여러개 가능



NOT NULL : 데이터에 NULL 허용 X
UNIQUE : 중복된 값 허용 X
PRIMARY KEY : NOT NULL + UNIQUE ← 고유 식별자로 사용 : 각 컬럼을 식별할 수 있는 고유 식별자
    - PRIMARY KEY로 고유 식별자로 사용. 이 지정한 걸로 행 구분이 되기에 중요
FOREIGN KEY : 외부 테이블에서 참조해 온 컬럼값이 존재하면 허용

*/

-- 제약조건 테스트 START
-- 테이블 생성


CREATE TABLE USER_NOCONST(
    USER_NO NUMBER,
    USER_ID VARCHAR2(20),
    USER_PWD VARCHAR2(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50)
);


INSERT INTO USER_NOCONST VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- 1 행 이(가) 삽입되었습니다.
INSERT INTO USER_NOCONST VALUES(NULL, NULL, NULL, NULL,NULL,NULL,NULL);
-- 1 행 이(가) 삽입되었습니다.
-- 아무런 제약조건이 없기에 데이터 추가가 가능했음


CREATE TABLE P_USER_NOCONST(
    USER_NO NUMBER,
    USER_ID VARCHAR(20),
    USER_PWD VARCHAR(20),
    USER_NAME VARCHAR(20),
    GENDER VARCHAR(20),
    PHONE VARCHAR(20),
    EMAIL VARCHAR(20)
);

INSERT INTO P_USER_NOCONST VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_NOCONST VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- 중복 삽입 가능

-- NULL 데이터에 제약조건 설정해보자

CREATE TABLE P_USER_NOTNULL(
    USER_NO NUMBER NOT NULL,
    USER_ID VARCHAR2(20)NOT NULL,
    USER_PWD VARCHAR2(30)NOT NULL,
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR(20),
    PHONE VARCHAR(20),
    EMAIL VARCHAR(20)
);
INSERT INTO P_USER_NOTNULL VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_NOTNULL VALUES(NULL, NULL, 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- ORA-01400: cannot insert NULL into ("KH"."P_USER_NOTNULL"."USER_NO")
-- "P_USER_NOTNULL"테이블의 "USER_NO"컬럼에서 NULL CONSTRAINT 조건 때문에 막힘
INSERT INTO P_USER_NOTNULL VALUES(2, 'user02', NULL, '강건강','남','010-1111-2222','kang@k.k');
-- ORA-01400: cannot insert NULL into ("KH"."P_USER_NOTNULL"."USER_PWD")
-- 제약 조건에 NOT NULL 걸어둔게 USER_NAME까지만이라 여기부터는 NULL이어도 삽입가능


-------------------------------------------------------------------------------------------


-- UNIQUE

-- 중복된 값 허용 X
-- 컬럼레벨, 테이블레벨 둘 다 설정가능


--중복제한걸기
CREATE TABLE P_USER_UNIQUE(
    USER_NO NUMBER,
    USER_ID VARCHAR2(20) UNIQUE,
    -- 컬럼레벨에서 제약조건 설정함. UNIQUE 제약조건 추가 // 컬럼레벨 : 컬럼에 제약조건 집어 넣은 것
    USER_PWD VARCHAR2(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50)
);
INSERT INTO P_USER_UNIQUE VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');



INSERT INTO P_USER_UNIQUE VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_UNIQUE VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- ERROR : ORA-00001: unique constraint (KH.SYS_C007021) violated
-- 유니크 제약조건이 위반됨. SYS_C007021 이부분이 제약조건 이름. 
-- 테이블의 해당 컬럼가서 제약조건 탭에 CONSTRAINT_NAME에 제약조건 이름이 있고 여기서 확인가능
-- DEVELOPER에서는 위처럼 확인가능하고 아래는 CMD


INSERT INTO P_USER_UNIQUE VALUES(2, 'user02', 'pass02', '강건강','남','010-1111-2222','kang@k.k');
-- 1 행 이(가) 삽입되었습니다.


CREATE TABLE P_USER_UNIQUE2(
    USER_NO NUMBER,
    USER_ID VARCHAR2(20),
    USER_PWD VARCHAR2(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50),
    UNIQUE(USER_ID) -- 테이블 레벨 : 아래에 제약조건 지정하는 것
    -- NOT NULL 제약조건은 테이블 레벨의 제약 조건 설정 불가능 -> 무조건 컬럼 레벨에서만 사용가능
);
INSERT INTO P_USER_UNIQUE2 VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- 1 행 이(가) 삽입되었습니다.
INSERT INTO P_USER_UNIQUE2 VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- ORA-00001: unique constraint (KH.SYS_C007049) violated
-- KH계정의 SYS_C007049 제약조건 위반



---RE
CREATE TABLE P_USER_UNIQUE (
    USER_NO NUMBER NOT NULL,
    USER_ID VARCHAR(20) UNIQUE,
    USER_PWD VARCHAR(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50),
    UNIQUE(USER_NO)
);
INSERT INTO P_USER_UNIQUE VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');

SELECT * FROM P_USER_UNIQUE;
SELECT * FROM USER_CONSTRAINTS;


CREATE TABLE P_USER_UNIQUE3 (
    USER_NO NUMBER,
    USER_ID VARCHAR2(20),
    USER_PWD VARCHAR2(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50),
    UNIQUE(USER_NO,USER_ID) -- 컬럼 2개를 하나로 묶기
); -- 컬럼1개 지정과 차이가 뭘지 해보자
INSERT INTO P_USER_UNIQUE3 VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_UNIQUE3 VALUES(1, 'user02', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_UNIQUE3 VALUES(2, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_UNIQUE3 VALUES(2, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
-- ORA-00001: unique constraint (KH.SYS_C007050) violated
-- 위의 3개는 삽입이 잘됬지만 마지막것만 3번줄이랑 겹쳐서 에러
-- UNIQUE(USER_NO,USER_ID)에서 USER_NO,USER_ID 둘을 한세트로 보고 
-- 두 값이 다 같아야 조건이겹치는 걸로 본다.

DROP TABLE P_USER_UNIQUE3 CASCADE CONSTRAINTS;

CREATE TABLE P_USER_UNIQUE4 (
    USER_NO NUMBER,
    USER_ID VARCHAR2(20),
    USER_PWD VARCHAR2(30),
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10),
    PHONE VARCHAR2(30),
    EMAIL VARCHAR2(50),
    UNIQUE(USER_NO,USER_ID)
);
INSERT INTO P_USER_UNIQUE4 VALUES(1, 'user01', 'pass01', '강건강','남','010-1111-2222','kang@k.k');
INSERT INTO P_USER_UNIQUE4 VALUES(1, 'user02', 'pass01', '강건강','남','010-1111-2222','kang@k.k');

SELECT * FROM USER_TABLES;
DROP TABLE P_USER_UNIQUE4;
DROP TABLE P_USER_UNIQUE4 CASCADE CONSTRAINTS;

------------------------------------------------------------------------------
-- < 제약조건 이름짓기>


CREATE TABLE P_CONS_NAME(
    CONS_TEST1 VARCHAR(20) CONSTRAINT PCN_CT1_NN NOT NULL, -- 제약조건 이름 짓기
    CONS_TEST2 VARCHAR(20) CONSTRAINT PCN_CT2_UQ UNIQUE,-- 유니크 컬럼레벨, 테이블레벨 둘 다 설정가능
    CONS_TEST3 VARCHAR(20),
    CONSTRAINT PCN_CT3_UK UNIQUE(CONS_TEST3)-- 유니크 컬럼레벨, 테이블레벨 둘 다 설정가능
);
-- CN_TD1_NN 의미
--    CN : 테이블 이름
--    TD1 : 컬럼 이름
--    NN : (제약조건) NOT NULL 의미
--    UQ(UK) : (제약조건) UNIQUE
DROP TABLE P_CONS_NAME CASCADE CONSTRAINTS;

INSERT INTO P_CONS_NAME VALUES('Z','A','B');
-- 테이블에서 제약조건 탭에 보면 CONSTRAINT_NAME에 이름이 바뀐 것을 확인할 수 있다

CREATE TABLE P_CONS_NAME3 (
    CTEST1  NUMBER CONSTRAINTS PCN_CT1_NN NOT NULL,
    CTEST2 VARCHAR2(10) CONSTRAINTS PCN_CT2_UQ UNIQUE,
    CTEST3 VARCHAR2(20)
);
SELECT * FROM USER_CONSTRAINTS;

DROP TABLE P_CONS_NAME3 CASCADE CONSTRAINTS;

------------------------------------------------------------------------------


-- PRIMARY KEY

-- PRIMARY KEY : NOT NULL + UNIQUE -> 고유 식별자 역할
-- 컬럼레벨, 테이블레벨 둘 다 설정가능
-- NOT NULL + UNIQUE -> **고유 식별자 역할**
-- 한 테이블 당 한번만 설정 가능
--    (고유 식별자는 고유한거니 하나만 가능. 컬럼마다 있다면 고유식별 불가능해지니)


CREATE TABLE P_U_PK(
     USER_NO NUMBER CONSTRAINT PUP_N_PK PRIMAY KE,
     USER_ID VARCHAR2(20),
     USER_PWD VARCHAR2(10)
    );

CREATE TABLE PK(
     USER_NO NUMBER ,
     USER_ID VARCHAR2(20),
     USER_PWD VARCHAR2(10),
    CONSTRAINT PK PRIMARY KEY(USER_NO,USER_ID)
);     

DROP TABLE PK CASCADE CONSTRAINTS;

------------------------------------------------------------------------------


-- FOREIGN KEY 
-- 참조
-- 외부 테이블에서 참조해 온 컬럼. 이 컬럼값이 존재하면 허용
-- 테이블 레벨, 컬럼 레벨 둘 다 설정가능

-- 부모테이블 : 참조 당하는 테이블
-- 자식테이블 : 참조하는 테이블

CREATE TABLE A (
    AA NUMBER PRIMARY KEY,
    BB VARCHAR2(30) NOT NULL
);
INSERT INTO A VALUES(10, 'A');
INSERT INTO A VALUES(20, 'B');

CREATE TABLE B(
    CC NUMBER PRIMARY KEY,
    DD VARCHAR2(30) UNIQUE,
    AA NUMBER NOT NULL,
    CONSTRAINT B_EE_FK FOREIGN KEY(AA) REFERENCES A(AA) ON DELETE SET NULL
);                                                   -- OM DELETE CASCADE
INSERT INTO B VALUES(1,'A',1);

-- <제약조건이 걸려있어도 삭제할 수 있는 방법>
-- ON DELETE SET NULL
-- 부모 키 삭제 시 자식 키를 NULL로 변경

-- ON DELETE CASCADE
-- 부모 키 삭제 시, 자식 키도 함께 삭제


------------------------------------------------------------------------------
-- CHECK
-- 
-- 데이터 값의 범위나 조건을 지정해 설정한 값만 허용

CREATE TABLE UC(
    USER_NO NUMBER PRIMARY KEY,
    USER_ID VARCHAR2(20) UNIQUE,
    USER_PWD VARCHAR2(30) NOT NULL,
    USER_NAME VARCHAR2(30),
    GENDER VARCHAR2(10) CHECK(GENDER IN('남','여'))
);
INSERT INTO UC VALUES(1,'A','AA','AAA','남');
INSERT INTO UC VALUES(2,'B','BB','BBB','M');
-- 남OR여만 들어가게 되었어 제약조건에 걸려 에러

-- 코멘트(설명) 달기
COMMENT ON COLUMN UC.USER_NO IS '회원번호';
COMMENT ON COLUMN UC.USER_ID IS '회원아이디';

------------------------------------------------------------------------------

-- SUBQUERY를 이용한 테이블 생성

CREATE TABLE P_EC
AS SELECT * FROM EMPLOYEE;

SELECT * FROM P_EC;

CREATE TABLE P_EC2
AS SELECT * 
FROM EMPLOYEE
    LEFT OUTER JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID)
    JOIN JOB USING(JOB_CODE);

SELECT * FROM P_EC2;
DROP TABLE P_EC2;

ALTER TABLE P_EC ADD PRIMARY KEY(EMP_ID);
ALTER TABLE P_EC ADD UNIQUE(EMP_NAME);
ALTER TABLE P_EC ADD CONSTRAINT PEC_EN_UQ UNIQUE(EMP_NO);
ALTER TABLE P_EC MODIFY 
------------------------------------------------------------------------------
-- DEPARTMENT 테이블의 LOCATION_ID에 외래키 제약조건 추가
-- 참조 테이블은 LOCATION, 참조 컬럼은 LOCATION의 기본키

ALTER TABLE DEPARTMENT ADD FOREIGN KEY(LOCATION_ID) REFERENCES LOCATION(LOCATION);

 

728x90
반응형
728x90



728x90
반응형

'small steps > 운동 - 체력이 국력' 카테고리의 다른 글

22.03.24 운동기록  (0) 2022.03.24
22.03.23 운동기록 - 어깨 집중 중  (0) 2022.03.23
22.03.17 운동기록  (0) 2022.03.17
22.03.15 운동기록  (0) 2022.03.16
22.03.12 운동기록  (0) 2022.03.13
728x90

 

ALTER, DROP - 컬럼 추가,삭제,수정, 컬럼명 변경, 제약조건 추가 ,삭제, 제약조견명 변경

테이블명 변경, 삭제

RENAME A TO B

ADD

MODIFY

 

/*
------------------------------------------------------------------------------
----------------------------------ALTER --------------------------------------
------------------------------------------------------------------------------

-- ALTER 
객체 수정

컬럼 추가/삭제, 제약조건 추가/삭제, 컬럼 자료형 변경, 디폴트값 변경
테이블명/컬럼명/제약조건명 변경


*/

-- 컬럼 추가/삭제/수정

SELECT * FROM UC;

-- 추가
ALTER TABLE UC ADD (PHONE NUMBER);
ALTER TABLE UC ADD (NATIONALITY VARCHAR2(20) DEFAULT '한국');
-- 컬럼 PHONE, NATIONALITY 추가완료. NATIONALITY 지정안하면 기본값으로 한국


DESC UC;
-- 수정
ALTER TABLE UC
MODIFY USER_ID VARCHAR2(30)
MODIFY GENDER CHAR(3) -- ERROR : ORA-01441: cannot decrease column length because some value is too big
MODIFY NATIONALITY DEFAULT '미국';  -- 바꿀 자료형의 크기가 들어있는 데이터보다 작으면 에러

-- 삭제
ALTER TABLE UC
DROP COLUMN PHONE; -- PHONE 컬럼 삭제


-- 제약 조건과 함께 컬럼 삭제
ALTER TABLE UC
DROP COLUMN USER_NAME CASCADE CONSTRAINT;

DESC UC;

------------------------------------------------------------------------------
------------------------------------------------------------------------------

ALTER TABLE TB1
DROP COLUMN COL1;


-- 제약 조건과 함께 삭제
ALTER TABLE TB1
DROP COLUMN PK1 CASCADE CONSTRAINTS;

SELECT * FROM UC;

-- 제약 조건 추가
ALTER TABLE UC ADD CONSTRAINT UC_GEN_UQ UNIQUE(GENDER);
ALTER TABLE UC ADD CONSTRAINT EMP_ENAME_UQ UNIQUE(USER_NO);
ALTER TABLE UC ADD CONSTRAINT EMP_ENAME_UQ UNIQUE(USER_NO);



-- 제약조건 삭제
ALTER TABLE UC DROP CONSTRAINT EMP_ENAME_UQ;

-- 제약조건 한번에 여러개 삭제
ALTER TABLE UC
DROP CONSTRAINT SYS_C007129
DROP CONSTRAINT SYS_C007130
DROP CONSTRAINT SYS_C007127; -- GENDER의 CHECK 남여조건 빼고 제약조건 다 삭제

-- 컬럼명 변경
-- RENAME A TO B : A를 B로 컬럼명 변경
ALTER TABLE UC
RENAME COLUMN GENDER TO GENDER2;
ALTER TABLE UC
RENAME COLUMN GENDER2 TO GENDER;

-- 제약조건 이름 변경
ALTER TABLE UC
RENAME CONSTRAINT SYS_C007128 TO UC_CHECK1; 

DESC UC;
------------------------------------------------------------------------------

--테이블명 변경
ALTER TABLE DEPT_COPY
RENAME TO DEPT_COPY2;

--테이블 삭제
DROP TABLE DEPT_COPY;
--테이블+제약조건 삭제
DROP TABLE DEPT_COPY
CASCADE CONSTRAINTS;
728x90
반응형
728x90

 

JOIN 

INNER JOIN, OUTER JOIN

오라클 전용구문, ANSI 표준구문

-- 04.JOIN ★★★

/*
JOIN이란?
하나 이상의 테이블에서 데이터를 조회하기 위해 사용
여러개의 테이블들을 연결하여 데이터를 조회


<JOIN 세부 종류>
1.내부 조인
데이터가 ‘같은 부분’끼리 연결
위의 특성 때문에 해당하지 않는 데이터는 제외하고 반환됨
    1)오라클 전용구문 
        FROM절에 해당 테이블 모두 기술
        테이블끼리 연결하는 부분은 WHERE을 통해 연결
    2)ANSI 표준구문
        FROM절에 해당되는 테이블 모두 기술
        JOIN 구문 이용 
            JOIN + ON : 두 데이터값이 다른 이름일 때
            JOIN + USING : 두 데이터값이 같은 이름일 때
            but, 이름이 같더라도 JOIN + ON 사용가능

2.외부 조인
데이터가 같지 않은 행도 조인에 포함
내부 조인의 공통 데이터만 추출하는 특성에서 한쪽만 충족하는 데이터를 더 가져 올 수 있게 한 조인
    1)오라클 전용구문
        맞춰주는 테이블(기준이 아닌 테이블)의 컬럼 쪽에 (+)
    2)ANSI 표준구문 : 좀 더 LEFT, RIGHT 직관적
        LEFT OUTER JOIN
        RIGHT OUTER JOIN
        FULL OUTER JOIN : 양쪽 다 기준
        (OUTER)는 생략 가능


*/

------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------

--1.내부조인(Inner join)
--    1)오라클 전용 구문
--          컬럼명이 같으면 어느 테이블 컬럼인지 지정해줘야함 : 테이블명.컬럼명으로 지정
--    2)ANSI 표준 구문
--          내가 연결할 컬럼의 이름이 다를 때 = ON 사용
--          내가 연결할 컬럼이 이름이 같을 때 = USING 사용
--               컬럼 이름이 같다고 해서 무조건 USING 사용? X  


-- 사번, 이름, 부서코드, 부서명
-- 오라클 전용 구문
SELECT EMP_ID, EMP_NAME, DEPT_ID, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID -- 결과값 21개. 부서코드가 NULL인 직원은 제외
ORDER BY DEPT_ID;         

-- ANSI 표준 구문
SELECT EMP_ID, EMP_NAME, DEPT_ID, DEPT_TITLE
FROM EMPLOYEE
    JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID);


-- 사번, 사원명, 직급코드, 직급명 // 각 사원에 대한 직급명 조회
-- 오라클 전용 구문
-- ANSI 표준 구문
-- 풀이과정
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, J.JOB_NAME
FROM EMPLOYEE "E", JOB "J"
WHERE E.JOB_CODE = J.JOB_CODE; -- 23행
-- JOIN ~ ON
SELECT EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, JOB_NAME
FROM EMPLOYEE
    JOIN JOB ON(EMPLOYEE.JOB_CODE = JOB.JOB_CODE);
SELECT EMP_ID, EMP_NAME, EMPLOYEE.JOB_CODE, JOB.JOB_NAME
FROM EMPLOYEE
    JOIN JOB ON(EMPLOYEE.JOB_CODE = JOB.JOB_CODE);
-- JOIN ~ USING
SELECT EMP_ID, EMP_NAME, JOB_CODE, JOB_NAME
FROM EMPLOYEE
    JOIN JOB USING(JOB_CODE); 
-- USING 쓰면 FROM EMPLOYEE테이블에 JOB테이블을 조인시키면서 명시되므로,
-- USUNG()안에 JOB.이라고 명시할 필요X
    
-- < ANSI 표준 구문>
-- 내가 연결할 컬럼의 이름이 다를 때 = ON 사용
-- 내가 연결할 컬럼이 이름이 같을 때 = USING 사용
--      컬럼 이름이 같다고 해서 무조건 USING 사용? X  

-- 테이블명 EMPLOYEE에 별칭 사용 연결
-- 오라클 전용구문
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, J.JOB_NAME
FROM EMPLOYEE "E", JOB "J"
WHERE E.JOB_CODE = J.JOB_CODE; -- 23행
-- ANSI 표준 구문
SELECT EMP_ID, EMP_NAME, E.JOB_CODE, J.JOB_NAME
FROM EMPLOYEE "E"
    JOIN JOB "J" ON(E.JOB_CODE = J.JOB_CODE); -- 23행


-- 부서명과 해당 부서의 지역명 조회
-- 오라클 전용 구문
-- ANSI 표준 구문
SELECT D.DEPT_TITLE, L.LOCAL_NAME
FROM DEPARTMENT "D", LOCATION "L"
WHERE D.LOCATION_ID = L.LOCAL_CODE;
-- 오라클 전용 구문
-- 경로지정X & 별칭X
SELECT DEPT_TITLE, LOCAL_NAME
FROM DEPARTMENT, LOCATION
WHERE LOCATION_ID = LOCAL_CODE;  -- 9행 인사관리부	ASIA1
-- ANSI 표준 구문
SELECT DEPT_TITLE, LOCAL_NAME
FROM DEPARTMENT
    JOIN LOCATION ON(LOCATION_ID = LOCAL_CODE); -- 9행 인사관리부	ASIA1


------------------------------------------------------------------------------
------------------------------------------------------------------------------
-----------------------------2.외부조인(Outer join)-----------------------------
------------------------------------------------------------------------------
/*
내부 조인의 한계
매칭이 안되는 값이 있으면 조인해서 가져올 수 없는 한계
-> 보완하는 것이 외부조인
내부조인 개념이 일치하는 것을 가져오는 것

 2.외부조인(Outer join)
 컬럼 값이 일치하지 않는 행도 조인에 포함시킴
 아우터 조인 무조건 명시해야함

종류
1.LEFT (OUTER) JOIN
2.RIGHT (OUTER) JOIN
3.FULL (OUTER) JOIN
    - 오라클 구문은 풀아우터 조인 사용불가
- (OUTER) : 생략가능
    

*/ 

-- INNER JOIN
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
    JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); 
    -- 21행 : DEPT_CODE가 NULL인 사람은 제외(매칭X)



SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
    JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); -- 21행 : DEPT_CODE가 NULL인 사람은 제외(매칭X)
    

--1.LEFT (OUTER) JOIN
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
    LEFT OUTER JOIN DEPARTMENT ON (DEPT_CODE = DEPT_ID);

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE = DEPT_ID(+);


-- 내부조인과 차이
-- 내부조인에서는 부서코드가 NULL인 직원은 제외되고 21행 나왔지만
-- LEFT OUTER JOIN은 NULL인 직원 2명도 포함했기에 23행 출력
 
/* 
내 기준으로 왼쪽에 있는 얘를 기준으로 삼겠다
즉 EMPLOYEE가 기준
디파트가 임플한테 맞춰주는 것. 
그래서 오라클 전용구문에서 표기가 기준점이 되는 테이블이 아닌 조이하는 테이블(+) 붙임
ex)WHERE DEPT_CODE = DEPT_ID(+);


<강사쌤 설명>
--레프트 라이트 조인 기준으로 왼쪽이면 임플로이 오른쪽이면 디파트
--레프트는 임플이 기준이라 임플로이 전부를 출력함(23개행). 내부조인 하면 하동운,이오리 안나옴.
--임플이 기준이라 NULL값도 출력을 해줌
--디파트가 임플 맞춰줘야함->23개행이 나올 수 있도록 

<내가 한 이해>
레프트 라이트 조인 기준으로 왼쪽이면 임플로이 오른쪽이면 디파트
임플로이에는 EMP_NAME에서 사원명 가져오는데 이게 23명이고,
디파에서는 DEPT_TITLE에서 부서명 가져오는데 이건 21개. 부서배정이 아직인 2명이
NULL로 나오는데 임플 기준이라 23행 맞춰줘야하니 부서명이 없는 2명은 NULL로 표시

 
Q.EMPLOYEE안에 DEPT_CODE가 있으니까 DEPT_CODE안에 NULL이 있어도 일단 쓰고, 
  DEPARTMENT를 DEPT_CODE에 맞춰서 나온거죠,,?
A.YES

*/


 
 
--2.RIGHT (OUTER) JOIN
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE(+) = DEPT_ID;

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
    RIGHT OUTER JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID);

-- ★양쪽 테이블의 매칭된 데이터 + 가져오길 원하는 한쪽 집합의 데이터★

--3.FULL (OUTER) JOIN
-- 둘 다 기준이 된다
SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE, DEPARTMENT
WHERE DEPT_CODE(+) = DEPT_ID(+);
-- ERROR :  a predicate may reference only one outer-joined table
-- 오라클 구문으로는 기준을 하나만 정할 수 있어 풀아우터조인은 사용불가

SELECT EMP_NAME, DEPT_TITLE
FROM EMPLOYEE
    FULL OUTER JOIN DEPARTMENT ON(DEPT_CODE = DEPT_ID); 
-- 26행 출력 : 
-- LEFT의 부서배정안된 22이오리23하동운 NULL 데이터 + RIGHT의 부서만 있고 직원 없는 
-- (NULL) 해외영업3부,마케팅부,국내영업부해서 
-- 내부조인 결과 21행에 LEFT 2행+ RIGHT 3행 = 21+2+3= 총26행
728x90
반응형
728x90

ORDER BY, GROUP BY, HAVING 

 

 


/*
<SELECT문의 구조>
SELECT
FROM
WHERE 
GROUP BY
HAVING
ORDER BY

<SELECT문의 구조>
SELECT : 컬럼명 AS 별칭, 계산식, 함수식       -> 조회하고자 하는 컬럼 기술
FROM : 테이블 명                           -> 컬럼이 속해 있는 테이블 기술
WHERE : WHERE 컬럼명|함수식 비교연산자 비교값 -> SELECT에 조건식 설정
GROUP BY : 그룹으로 묶을 컬럼명              -> 그룹함수가 적용될 그룹 기술
HAVING : 그룹함수식 비교연산자 비교값         -> 그룹함수에 조건식 설정
ORDER BY : 컬럼명|별칭|컬럼 순번 정렬방식 [NULLS FIRST | LAST]; -> 정렬 조건 기술
    - SELECT에서 별칭을 써두었다면, 별칭으로도 정렬 가능


<실행순서>
1)FROM : 실행해서 판을 깔고
2)WHERE : 조건 추려내고 보고 싶은 컬럼들만 취함
3)GROUP BY
4)HAVING
5)SELECT
6)ORDER BY


*/


------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- ORDER BY
-- 정렬
-- 오름차순 ASC / 내림차순 DESC
--   생략 가능  /   생략 불가
-- 오름차순에서 NULL은 마지막에 배치
-- 내림차순에서 NULL은 첫 배치
-- 별칭,번호로 정렬 가능

SELECT EMP_ID, EMP_NAME, SALARY, DEPT_CODE
FROM EMPLOYEE
-- 이름으로 오름차순(ASC)
--ORDER BY EMP_NAME ASC;
-- ASC는 생략가능. 
--ORDER BY EMP_NAME;
-- 내림차순은 생략 불가. 명시적
--ORDER BY EMP_NAME DESC;
-- NULL이 들어가 있는 값은 나중에 배치한 상태로 오름차순
--ORDER BY DEPT_CODE;
-- NULL을 먼저 배치 후 내림차순
--ORDER BY DEPT_CODE DESC;
--ORDER BY DEPT_CODE DESC NULLS FIRST;
-- 오름차순일 때는 NULL을 나중에 배치하는게 기본, 내림차순일 때는 NULL을 먼저 배치하는게 기본
ORDER BY DEPT_CODE DESC NULLS LAST;


-- 별칭으로 정렬해보자
SELECT EMP_ID, EMP_NAME, SALARY 급여, DEPT_CODE -- 급여 : 별칭
FROM EMPLOYEE
--ORDER BY SALARY;
--ORDER BY 급여;
-- 2는 EMP_NAME 대해
--ORDER BY 2 DESC;
-- 3은 SALARY에 대해 내림차순
ORDER BY 3 DESC;


-- 셀렉트가 오더바이보다 먼저 진행. 그래서 별칭을 읽어올 수 있는 것. 아래 실행순서 참조
-- ORDER BY 이외에 별칭을 읽을 수 있는게 없다. 코드 내 실행 순서 때문
-- 별칭은 컬럼이 아니라 없는 데이터를 가져올려하니 에러 : invailid identifier


/*
실행순서
1)FROM부터 실행해서 판을 깔고
2)WHERE 통해서 조건 추려내고
보고 싶은 컬럼들만 취함
3)GROUP BY
4)HAVING
5)SELECT
6)ORDER BY
*/


------------------------------------------------------------------------------
------------------------------------------------------------------------------
--------------------------------GROUP BY--------------------------------------
------------------------------------------------------------------------------


-- GROUP BY
-- 데이터들을 원하는 그룹으로 나눌 때 사용
-- 그룹함수으로 묶을 기준을 제안하는 것
-- 그룹함수가 적용될 그룹 기술


-- 부서 별 급여 합계 조회
SELECT SUM(SALARY), DEPT_CODE -- ERROR : not a single-group group function
FROM EMPLOYEE; -- 위 메세지에서의 SINGLE은 여러행 그룹은 ...?
-- 싱글과 그룹 함께 사용할 수 없다는 의미 // 결과가 하나만 나와야하는 그룹함수인데 여러행이 나오는 단일 행 함수와 혼용 불가
-- 싱글 : SUM(SALARY)
-- 그룹 : DEPT_CODE

-- 부서 별 급여 합계한다고하면 먼저 부서별로 그룹부터 나눌 것
-- 각각의 부서 그룹의 샐러리 합계 구해나아갈 것. 
-- 컴한테 어떤 것들을 그룹 지을지 알려줘야 계산할 수 있다




-- EMPYLOEE테이블에서 부서 별 급여 합계, 급여 평균, 인원 수를 조회
-- 그룹화 할 때는 그룹화의 기준이 되는 컬럼은 가능해보임
SELECT DEPT_CODE, SUM(SALARY), AVG(SALARY), COUNT(*)
FROM EMPLOYEE
GROUP BY DEPT_CODE;
-- 그룹지어지는 대상과 일반함수와 같아야한다. 
-- GROUP BY에 넣을 컬럼명과 SELECT 오른쪽 컬럼명이 같아야함


-- EMPLOYEE테이블에서 부서코드와 보너스 받는 사원수 조회
SELECT DEPT_CODE, COUNT(BONUS)
FROM EMPLOYEE
GROUP BY DEPT_CODE
ORDER BY DEPT_CODE;


-- IS NOT NULL 사용
SELECT DEPT_CODE, COUNT(BONUS)
FROM EMPLOYEE
WHERE BONUS IS NOT NULL
GROUP BY DEPT_CODE
ORDER BY DEPT_CODE;
-- 결과에 어떤 영향이? 
-- D2부서에서 보너스 받는 사람이 없는데 이게 안나옴




--WHERE BONUS IS NOT NULL -- WHERE절이 없으면 COUNT(*)는 사람수를 카운트함

--EMPLOYEE테이블에서 직급코드, 보너스를 받는 사원수 조회
SELECT JOB_CODE, COUNT(BONUS)
FROM EMPLOYEE
GROUP BY JOB_CODE;
-- 보너스 안받는 사람을 안보고 싶다면, WHERE BONUS IS NOT NULL 추가 







--EMPLOYEE테이블에서 성별과 성별 별 급여 평균(정수처리(보통 내림하라는 의미)), 급여합계, 인원 수 조회(인원수로 내림차순)
SELECT FLOOR(AVG(SALARY)),SUM(SALARY), COUNT(*), 
        DECODE(SUBSTR(EMP_NO,8,1),1,'남',2,'여') -- SELECT문 첫번째로 GROUP BY 기준점이랑 안나와도 되는듯
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1);


SELECT FLOOR(AVG(SALARY)),SUM(SALARY), COUNT(*),
        CASE WHEN SUBSTR(EMP_NO,8,1) = 1 THEN '남'
             WHEN SUBSTR(EMP_NO,8,1) = 2 THEN '여'
            -- ELSE '여'
        END 성별
FROM employee
GROUP BY SUBSTR(EMP_NO,8,1);

---RE
SELECT FLOOR(AVG(SALARY)),SUM(SALARY), COUNT(*),
        DECODE(SUBSTR(EMP_NO,8,1),1,'남','여')
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1)
ORDER BY COUNT(*) DESC;


--EMPLOYEE테이블에서 성별과 성별 별 급여 평균(정수처리(보통 내림하라는 의미)), 급여합계, 인원 수 조회(인원수로 내림차순)
-- 데이터에 직접적으로 없는 데이터를 GROUP BY해서 평균,합계,수 조회해야함
-- CASE WHEN
SELECT FLOOR(AVG(SALARY)), SUM(SALARY), COUNT(*) ,
        CASE WHEN SUBSTR(EMP_NO,8,1)=1 THEN '남'
             WHEN SUBSTR(EMP_NO,8,1)=2 THEN '여'
        END "성별"
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1)
ORDER BY COUNT(*) DESC;

-- DECODE
SELECT DECODE(SUBSTR(EMP_NO,8,1),1,'남','여')성별, FLOOR(AVG(SALARY)), SUM(SALARY), COUNT(*)
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1)
ORDER BY COUNT(*) DESC;


-- EMPLOYEE테이블에서 부서 코드별로 같은 직급인 사원의 급여 합계 조회
SELECT DEPT_CODE, JOB_CODE, SUM(SALARY)
FROM EMPLOYEE 
GROUP BY DEPT_CODE, JOB_CODE;

-- EMPLOYEE테이블에서 부서 코드별로 같은 직급인 사원의 급여 합계 조회
-- 부서별, 동 직급별 2개의 그룹핑 필요
-- 모범 답안
SELECT DEPT_CODE, JOB_CODE, SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE,JOB_CODE;



------------------------------------------------------------------------------
------------------------------------HAVING------------------------------------
------------------------------------------------------------------------------

-- HAVING
-- 조건절
-- 비슷 = WHERE
-- 차이 WHERE 대상 일반 컬럼
--     HAVING 대상 GROUP BY의 데이터


-- 1)부서 코드와 급여 3000000이상인 직원의 그룹 별 평균 급여 조회
-- 2)부서 코드와 급여 평균 3000000이상인 그룹 별 평균급여 조회

-- 1)부서 코드와 급여 3000000이상인 직원의 그룹 별 평균 급여 조회
-- 모범 답안

SELECT DEPT_CODE,AVG(SALARY)
FROM EMPLOYEE
WHERE SALARY >= 3000000
GROUP BY DEPT_CODE;


-- 2)부서 코드와 급여 평균 3000000이상인 그룹 별 평균급여 조회

SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE SALARY >= 300000
GROUP BY DEPT_CODE;

SELECT DEPT_CODE, AVG(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING AVG(SALARY) >= 3000000;


-- 부서 별 급여 합계 중 900000을 초과하는 부서코드와 급여 합계 조회
-- 모범 답안


SELECT DEPT_CODE, SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING SUM(SALARY) > 900000
ORDER BY DEPT_CODE;

------------------------------------------------------------------------------
----------------------------------다시풀어보기----------------------------------

--EMPLOYEE테이블에서 성별과 성별 별 급여 평균(정수처리(보통 내림하라는 의미)), 급여합계, 인원 수 조회(인원수로 내림차순)
-- 데이터에 직접적으로 없는 데이터를 GROUP BY해서 평균,합계,수 조회해야함

SELECT FLOOR(AVG(SALARY)), SUM(SALARY), COUNT(*),
        DECODE(SUBSTR(EMP_NO,8,1),1,'남','여')
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1)
ORDER BY COUNT(*) DESC; 

SELECT FLOOR(AVG(SALARY)), SUM(SALARY), COUNT(*),
        CASE WHEN SUBSTR(EMP_NO,8,1)=1 THEN '남'
             ELSE '여'
        END 성별
FROM EMPLOYEE
GROUP BY SUBSTR(EMP_NO,8,1)
ORDER BY COUNT(*) DESC; 

-- EMPLOYEE테이블에서 부서 코드별로 같은 직급인 사원의 급여 합계 조회
-- 부서별, 동 직급별 2개의 그룹핑 필요

SELECT DEPT_CODE, JOB_CODE, SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE, JOB_CODE;


-- 1)부서 코드와 급여 3000000이상인 직원의 그룹 별 평균 급여 조회
-- 2)부서 코드와 급여 평균 3000000이상인 그룹 별 평균급여 조회

SELECT DEPT_CODE, AVG(SALARY)
FROM EMPLOYEE
WHERE SALARY >= 3000000
GROUP BY DEPT_CODE;

SELECT DEPT_CODE, AVG(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE, SALARY
HAVING SALARY >= 3000000;

-- 2)부서 코드와 급여 평균 3000000이상인 그룹 별 평균급여 조회
SELECT DEPT_CODE, AVG(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING AVG(SALARY) >= 3000000;


---RE
SELECT DEPT_CODE, AVG(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING AVG(SALARY) >= 3000000;

-- 부서 별 급여 합계 중 900000을 초과하는 부서코드와 급여 합계 조회

SELECT DEPT_CODE,SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING SUM(SALARY) > 900000
ORDER BY DEPT_CODE;


---RE
SELECT DEPT_CODE, SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE
HAVING SUM(SALARY) > 900000;

------------------------------------------------------------------------------
------------------------------------------------------------------------------



-- ROLLUP, CUBE
-- 집계 함수 : 그룹별 산출한 결과물을 집계하는 함수
-- 집계 함수를 쓴다는건 산출한 결과물들을 가지고 집계해주는거 맞구나 생각드는데 근데
--
-- 롤업 큐브 차이점
-- 롤업은 인자로 전달받은 것 중 첫번째 한번만 집계
-- 큐브는 인자로 지정된 모든 것들에 대해 중간 집계
--      ex)ROLLUP : GROUP BY로 그루핑된 첫그룹의 종류별로 합계 반환
--      ex)CUBE : GROUP BY로 그루핑된 첫그룹의 종류별로 합계 반환한 후, 두번째 그룹의 합계 또 반환

SELECT JOB_CODE, SUM(SALARY)
FROM EMPLOYEE
--GROUP BY JOB_CODE           -- 각 직급 코드별 합계 7행
--GROUP BY ROLLUP(JOB_CODE) -- 롤업이나 큐브코드 추가시 행이 하나 더 생김. 마지막행의 데이터는 총합
GROUP BY CUBE(JOB_CODE) --
ORDER BY JOB_CODE;


--EMPLOYEE테이블에서 각 부서코드마다 직급코드 별 급여 합, 부서 별 급여 합, 총합 조회
SELECT DEPT_CODE,JOB_CODE, SUM(SALARY)
FROM EMPLOYEE 
GROUP BY DEPT_CODE, JOB_CODE
ORDER BY DEPT_CODE;


---RE
SELECT DEPT_CODE, JOB_CODE,SUM(SALARY)
FROM EMPLOYEE
GROUP BY DEPT_CODE, JOB_CODE;

-- ROLLUP
SELECT DEPT_CODE,JOB_CODE, SUM(SALARY)
FROM EMPLOYEE
GROUP BY ROLLUP (DEPT_CODE, JOB_CODE);

-- CUBE
-- 그룹별 산출한 결과를 집계하는 함수
-- 롤업은 인자로 전달받은 것 중 첫번째 한번만 집계
-- 큐브는 인자로 지정된 모든 것들에 대해 중간 집계



------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------SET OPERATION----------------------------------
------------------------------------------------------------------------------


-- SET OPERATION : 집합 연산자
-- 두 개 이상의 테이블에서 조인을 사용하지 않고 연관된 데이터를 조회하는 방법

-- 종류
-- UNION : 합집합 OR조건
-- INTERSECT : 교집합 AND조건
-- MINUS : 차집합 A-B
-- 쿼리의 결과와 쿼리의 결과를 하나로 합쳐 해당 함수의 적용, 결과를 반환

-- 합집합 A OR B
-- 교집합 A AND B 공통분모
-- 차집합 A - B
-- 여집합 A B를 제외한 나머지

-- UNION : 합집합 OR조건
-- INTERSECT : 교집합 AND조건
-- MINUS : 차집합 A-B
-- UNION ALL : AND조건 + OR조건(중복된 행 추가조회)
-- 

------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- UNION : 합집합
-- 두 쿼리를 결과를 하나로 합쳐 AND조건으로 반환
-- 왜 사용? WHERE절에 조건을 다 쓰거나 OR로 처리하기 힘들 경우
-- UNION 미적용
SELECT EMP_ID, EMP_NAME
FROM EMPLOYEE
WHERE EMP_ID = 200; -- 선동일
SELECT EMP_ID, EMP_NAME
FROM EMPLOYEE
WHERE EMP_ID = 201; -- 송종기
-- UNION 적용
SELECT EMP_ID, EMP_NAME
FROM EMPLOYEE
WHERE EMP_ID = 200 
UNION
SELECT EMP_ID, EMP_NAME
FROM EMPLOYEE
WHERE EMP_ID = 201; -- 선동일 송종기
--같은방법
SELECT EMP_ID, EMP_NAME
FROM EMPLOYEE
WHERE EMP_ID = 200  OR EMP_ID = 201;


-- EMPLOYEE테이블에서 DEPT_CODE가 D5이거나 급여가 300000을 초과하는 
-- 직원의 사번, 이름, 부서코드, 급여조회
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE DEPT_CODE = 'D5' OR SALARY = 300000;
-- UNION 적용
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE DEPT_CODE = 'D5' 
UNION
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY = 300000;


------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- INTERSECT : 교집합
-- 쿼리의 결과와 쿼리의 결과를 하나로 합쳐 OR조건 적용, 결과를 반환
-- INTERSECT 사용
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE DEPT_CODE = 'D5' 
INTERSECT
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY = 300000;

SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE DEPT_CODE = 'D5' 
INTERSECT
SELECT EMP_ID, EMP_NAME, DEPT_CODE, SALARY
FROM EMPLOYEE
WHERE SALARY > 300000;
--집합연산자에서 SELECT 절은 동일해야 되고 FROM절은 달라도 대나요?
-- 가능


------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- MINUS : 차집합

-- DEPT코드가 D5이면서 연봉이 3000000초과인 사람을 도출하는 코드

-- UNINON ALL
--

 

 

 

728x90
반응형
728x90

3.날짜 함수

SYSDATE

MONTHS_BETWEEN

ADD_MONTHS

NEXT_DAY

LAST_DAY

EXTRACT

 

4.형변환 함수

1)TO_CHAR()

2)TO_DATE()

3)TO_NUMBER()

 

5.NULL처리 함수

NVL

NVL2

NULLIF

 

6.선택함수

DECODE : 

CASE WHEN THEN

 

그룹함수

SUM,AVG,MIN/MAX,COUNT

-- 3)날짜 관련 함수

-- SYSDATE
-- 시스템에 저장되어있는 시간을 사용

SELECT SYSDATE FROM DUAL; -- 22/03/14



-- MONTHS_BETWEEN
-- ex) MONTHS_BETWEEN(SYSDATE, HIRE_DATE)
-- 개월수의 차를 숫자로 리턴해주는 함수
SELECT MONTHS_BETWEEN(SYSDATE, HIRE_DATE) FROM EMPLOYEE; -- 385일 차이
SELECT SYSDATE,HIRE_DATE, MONTHS_BETWEEN(SYSDATE, HIRE_DATE) FROM EMPLOYEE;
SELECT SYSDATE,HIRE_DATE, ABS(MONTHS_BETWEEN(SYSDATE, HIRE_DATE)) FROM EMPLOYEE;


-- EMPLOYEE테이블에서 사원의 이름, 입사일, 근무 개월 수 조회
SELECT EMP_NAME, HIRE_DATE, MONTHS_BETWEEN(SYSDATE,HIRE_DATE) "근무 개월 수"
FROM EMPLOYEE;

SELECT EMP_NAME, HIRE_DATE, CEIL(ABS(MONTHS_BETWEEN(HIRE_DATE, SYSDATE))) || '개월차'
FROM EMPLOYEE; -- 368개월차
-- 앞뒤로 뭐가 올지 모른다면 ABS를 넣어서 절대값으로 받아오면 된다

SELECT EMP_NAME, HIRE_DATE, CEIL(MONTHS_BETWEEN(SYSDATE,HIRE_DATE)) || '일수'"근무일수" FROM EMPLOYEE;




-- ADD_MONTHS
-- 기준 날짜에다 지정한 숫자만큼의 개월수로 더한 날짜 리턴
SELECT ADD_MONTHS(SYSDATE,4) FROM EMPLOYEE; -- 22/07/19
-- 지금부터 4개월 뒤 반환
SELECT ADD_MONTHS(SYSDATE,12) FROM EMPLOYEE; -- 23/03/19
-- 개월수가 더해져서 연도가 넘어가면 연도도 올라감

--EMPLOYEE테이블에서 사원의 이름, 입사일, 입사 후 6개월이 된 날짜 조회
SELECT EMP_NAME, HIRE_DATE, ADD_MONTHS(HIRE_DATE,6) FROM EMPLOYEE;
SELECT EMP_NAME, ADD_MONTHS('00/01/01',12) FROM EMPLOYEE; -- 01/01/01
-- 마이너스 -12개월
SELECT EMP_NAME, ADD_MONTHS('00/01/01',-12) FROM EMPLOYEE; -- 99/01/01



-- NEXT_DAY
-- 기준 날짜에서 구하려는 요일에 가장 가까운 날짜 리턴
-- 1=일, 2=월, 3=화,4=수, 5=목, 6=금, 7=토
-- 텍스트의 맨 앞글자만 따와서 요일 반환

SELECT SYSDATE, NEXT_DAY(SYSDATE, '일') FROM DUAL; -- 22/03/19	22/03/20
SELECT SYSDATE, NEXT_DAY(SYSDATE, '토') FROM DUAL; -- 22/03/19	22/03/26

-- 지금 기준으로부터 가장 가까운 목요일 구하기
SELECT NEXT_DAY(SYSDATE, '목') FROM DUAL;    -- 22/03/24
SELECT NEXT_DAY(SYSDATE, '목요일') FROM DUAL; -- 22/03/24
SELECT NEXT_DAY(SYSDATE, 5) FROM DUAL;       -- 22/03/24   
-- 1=일, 2=월, 3=화,4=수, 5=목, 6=금, 7=토
SELECT NEXT_DAY(SYSDATE, 'THUR') FROM DUAL; -- ERROR :  not a valid day of the week



SELECT SYSDATE, NEXT_DAY(SYSDATE, '목성주기') FROM DUAL; -- 22/03/19	22/03/24
-- 요일과 관련 없는 단어지만 맨 앞글자 '목'만 따서 요일 반환하는 걸 알 수 있다
SELECT SYSDATE, NEXT_DAY(SYSDATE, '금성') FROM DUAL; -- 22/03/19	22/03/25
-- 금성의 맨 앞글자 '금' = 금요일


-- 한글만 인지하게끔 설정이 되어있어 인식오류 뜨는 것

-- 영어로 세팅
ALTER SESSION SET NLS_LANGUAGE = AMERICAN; -- Session이(가) 변경되었습니다.
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURSDAY') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURSTY') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR--') FROM DUAL; -- 22/03/15	22/03/17
-- 한글과 동일하게 앞글자만 맞으면 요일 반환. 아마도 첫발음의 한글자를 치는 듯

SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURDAY') FROM DUAL; -- 22/03/19	22/03/24
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR') FROM DUAL;    -- 22/03/19	22/03/24
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR---') FROM DUAL;


-- 한글로 세팅
ALTER SESSION SET NLS_LANGUAGE = KOREAN; -- Session이(가) 변경되었습니다.

SELECT NEXT_DAY(SYSDATE, '금') FROM DUAL; -- 22/03/25
SELECT NEXT_DAY(SYSDATE, '금성') FROM DUAL;


-- LAST_DAY
-- 해당 날짜의 월의 마지막 일 반환
SELECT LAST_DAY(SYSDATE) FROM DUAL; -- 22/03/31
SELECT LAST_DAY(HIRE_DATE) FROM EMPLOYEE; -- 90/02/28 01/09/30
SELECT LAST_DAY(JOB_CODE) FROM EMPLOYEE; -- ERROR
-- ORA-01841: (full) year must be between -4713 and +9999, and not be 0


-- EXTRACT
-- 년, 월, 일 정보 추출 반환
-- 시간은 추출 불가

SELECT EXTRACT(SYSDATE-hire_date) FROM EMPLOYEE;

SELECT EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE),
       EXTRACT(DAY FROM SYSDATE) FROM EMPLOYEE; -- 2022	3	19
SELECT EXTRACT(DAY FROM SYSDATE)
--        EXTRACT(HOUR FROM SYSDATE),  -- 시간은 추출 불가
--        EXTRACT(MINUTE FROM SYSDATE) 
FROM EMPLOYEE;
       
-- EMPLOYEE테이블에서 사원의 이름, 입사연도, 입사월, 입사일 조회

SELECT EMP_NAME, EXTRACT(YEAR FROM HIRE_DATE) 입사연도,
                 EXTRACT(MONTH FROM HIRE_DATE) 입사월, 
                 EXTRACT(MONTH FROM HIRE_DATE) 입사일
FROM EMPLOYEE; -- 선동일	1990	2	2


-- EMPLOYEE테이블에서 사원의 이름, 입사일, 근무년수 조회
-- 단, 근무년수는 현재연도 - 입사연도로 조회
SELECT EMP_NAME,HIRE_DATE, SYSDATE,
        EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM HIRE_DATE) 근무년수
FROM EMPLOYEE; -- 선동일	90/02/06	22/03/19	32





----------실습문제------------
--1.EMPLOYEE테이블에서 사원명, 입사일-오늘, 오늘-입사일 조회
-- 단, 별칭은 근무일수1, 근무일수2로 하고 모두 정수처리(내림)와 양수로 처리
--2.EMPLOYEE테이블에서 사번이 홀수인 직원들의 정보 모두 조회
--3.EMPLOYEE테이블에서 근무년수가 20년 이상인 직원 전체 정보 조회
--4.EMPLOYEE테이블에서 사원명, 입사일, 입사한 달의 근무일수 조회


--1.EMPLOYEE테이블에서 사원명, 입사일-오늘, 오늘-입사일 조회
-- 단, 별칭은 근무일수1, 근무일수2로 하고 모두 정수처리(내림)와 양수로 처리
-- 절삭이 아니라 내림이라 FLOOR. TRUNC는 절삭이고 FLOOR는 수학적 내림
SELECT EMP_NAME, FLOOR(ABS(HIRE_DATE - SYSDATE)) 근무일수1, 
                FLOOR(ABS(SYSDATE - HIRE_DATE)) 근무일수2
FROM EMPLOYEE;

SELECT EMP_NAME, ABS(FLOOR(HIRE_DATE - SYSDATE)) 근무일수1, FLOOR(SYSDATE - HIRE_DATE) 근무일수2 
FROM EMPLOYEE;  

SELECT EMP_NAME, FLOOR(ABS(HIRE_DATE - SYSDATE)) 근무일수1, FLOOR(ABS(SYSDATE - HIRE_DATE)) 근무일수2 
FROM EMPLOYEE;  

--2.EMPLOYEE테이블에서 사번이 홀수인 직원들의 정보 모두 조회
-- 오라클에서는 % 나머지 연산지 지원X
SELECT *
FROM EMPLOYEE
WHERE MOD(EMP_ID,2) = 1;
--WHERE MOD(EMP_ID,2) != 0;

--3.EMPLOYEE테이블에서 근무년수가 20년 이상인 직원 전체 정보 조회
-- 방법1
SELECT *
FROM EMPLOYEE
WHERE CEIL(ABS(MONTHS_BETWEEN(SYSDATE, HIRE_DATE)))/12 >=20;

-- MONTHS_BETWEEN 반환값 확인방법
SELECT EMP_NAME, CEIL(ABS(MONTHS_BETWEEN(HIRE_DATE, SYSDATE)))
--SELECT EMP_NAME, ABS(MONTHS_BETWEEN(HIRE_DATE, SYSDATE))
FROM EMPLOYEE
WHERE CEIL(ABS(MONTHS_BETWEEN(SYSDATE ,HIRE_DATE))) >=20;

-- 방법2
SELECT *
FROM EMPLOYEE
WHERE ABS(MONTHS_BETWEEN(SYSDATE, HIRE_DATE))/12 >=20;

-- 방법3
SELECT * FROM EMPLOYEE
WHERE MONTHS_BETWEEN(SYSDATE, HIRE_DATE)>=240;
-- 방법4
SELECT *  FROM EMPLOYEE
WHERE (SYSDATE - HIRE_DATE) >= 365*20;
-- 방법5
SELECT *
FROM EMPLOYEE
WHERE ADD_MONTHS(HIRE_DATE,240) <= SYSDATE;
 
--4.EMPLOYEE테이블에서 사원명, 입사일, 입사한 달의 근무일수 조회
SELECT EMP_NAME 사원명, HIRE_DATE 입사일, 
    EXTRACT(DAY FROM LAST_DAY(HIRE_DATE))- EXTRACT(DAY FROM HIRE_DATE) "입사한 달의 근무일수"
FROM EMPLOYEE;

SELECT EMP_NAME, HIRE_DATE, LAST_DAY(HIRE_DATE) - HIRE_DATE
FROM EMPLOYEE;

------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------



-- 4)형변환 함수
-- A) TO_CHAR
-- B) TO_DATE
-- C) TO_NUMBER

-- A) TO_CHAR : 날짜/숫자형 데이터를 문자형 데이터로 변경
-- B) TO_DATE : 문자/숫자형 데이터를 날짜형 데이터로 변환
-- C) TO_NUMBER : 문자형 데이터를 숫자형 데이터로 변환


-- A) TO_CHAR 
-- 날짜/숫자형 데이터를 문자형 데이터로 변경
-- 자릿수에 맞춰 문자로 형변환
-- TO_CHAR(형변환할 날짜or숫자OR컬럼명, 전체자릿수 0 OR 9)
--      여분공간을 0은 0으로 9는 공백으로
    -- 남은 공백은 왼쪽에 표시
SELECT 1234 LITERAL_NUMBER FROM DUAL; -- 1234
SELECT 12345 LITERAL_NUMBER FROM DUAL;
SELECT TO_CHAR(1234) FROM DUAL; -- 1234
SELECT TO_CHAR('1234') FROM DUAL; -- 문자to문자 형변환 가능
SELECT 1234 LITERAL_NUMBER , TO_CHAR(1234) FROM DUAL; -- 1234	1234
SELECT 1234 "   숫자   ", TO_CHAR(1234) "   문자   " FROM DUAL;
-- 숫자로 인지되었으면 오른쪽 정렬, 문자로 인지되어있으면 왼쪽 정렬
-- 글자가 어디에 들어가 있느냐에 따라서 문자인지 숫자인지 구분 가능

SELECT 369 + 963, TO_CHAR(369)+TO_CHAR(963) FROM DUAL; -- 1332
SELECT 1234+4321, TO_CHAR(1234)+TO_CHAR(4321) FROM DUAL; -- 5555	5555 
-- 문자인데 연산이 가능한 이유 : 숫자로 형변환에 문제 없는 문자는 오라클에서 자동으로 연산해줌
-- 문자 연산 가능 // 자바에선 불가능

SELECT TO_CHAR(2222, '999999') FROM DUAL;  --    2222//
SELECT TO_CHAR(2222, '000000') FROM DUAL;  --  002222//
SELECT TO_CHAR(2222, '111111') FROM DUAL;  --  ERROR:ORA-01481: invalid number format model
SELECT TO_CHAR(1234, '99999') FROM DUAL;   --  (공백)1234
SELECT TO_CHAR(1234, '99999') A FROM DUAL; --  (공백)1234
-- '99999'의 의미는 5칸을 만들겠다. 여기에 1234를 넣고 빈 공간은 공백으로 하겠다는 의미
-- ' ' 안에는 9와 0만 가능. 다른 숫자는 에러 
SELECT TO_CHAR(1234, '99') A FROM DUAL;    -- ###
SELECT TO_CHAR(1234, '88') A FROM DUAL;    -- ERROR
SELECT TO_CHAR(1234,'00000') A FROM DUAL;  -- 01234
-- 비어있는 곳을 0으로 채워라


SELECT TO_CHAR(1234,'$99999') FROM DUAL; --   $1234
SELECT TO_CHAR(1234,'L99999') FROM DUAL;     --         ₩1234
-- L을 붙인건 현재 설정된 나라의 원화표시를 붙인 것
SELECT TO_CHAR(1234,'FML99999') FROM DUAL;   -- ₩1234
-- FM을 추가로 넣으면 공백 없애는 것
SELECT TO_CHAR(1234,'$99999') FROM DUAL;     --   $1234
-- 달러를 찍고 싶으면 L대신 $기호
SELECT TO_CHAR(1234,'FM$99999') FROM DUAL;   --$1234
SELECT TO_CHAR(1234,'99,999') FROM DUAL;     --  1,234
SELECT TO_CHAR(1234,'FM99,999') FROM DUAL;   -- 1,234
SELECT TO_CHAR(1234,'00,000') FROM DUAL;     --  01,234
SELECT TO_CHAR(1234,'FM00,000') FROM DUAL;   -- 01,234
SELECT TO_CHAR(1234,'999') FROM DUAL; -- ####
-- 자릿수가 부족해서 ####으로 대체 출력

-- 1234보다 더 적은 자리수를 지정할 경우는?
-- ##을 이용하면 됨



-- EMPLOYEE테이블에서 사원명, 급여(\(원화표시)9,000,000 형식) 조회
-- 모범 답안
SELECT EMP_NAME, TO_CHAR(SALARY, 'L999,999,999')
--SELECT EMP_NAME, TO_CHAR(SALARY, 'FML999,999,999')
FROM EMPLOYEE;


SELECT EMP_NAME,TO_CHAR(SALARY,'L9,999,999')
FROM EMPLOYEE; --         ₩8,000,000
SELECT EMP_NAME,TO_CHAR(SALARY,'L999,999,999') 
FROM EMPLOYEE; --           ₩8,000,000
SELECT EMP_NAME,TO_CHAR(SALARY,'FML999,999,999') 
FROM EMPLOYEE; -- ₩8,000,000


-- 시간
SELECT TO_CHAR(SYSDATE, 'HH:MI:SS') FROM DUAL; -- 03:40:27
SELECT TO_CHAR(SYSDATE, 'AM:HH:MI:SS') FROM DUAL; -- 오후:03:41:01
SELECT TO_CHAR(SYSDATE, 'PM:HH:MI:SS') FROM DUAL; -- 오후:03:41:43
SELECT TO_CHAR(SYSDATE, 'AM:HH24:MI:SS') FROM DUAL; -- 오후:15:42:38
SELECT TO_CHAR(SYSDATE, 'HH24:MI:SS') FROM DUAL;    -- 15:43:02
-- 날짜
SELECT TO_CHAR(SYSDATE, 'YY-MM-DD') FROM DUAL;                  --22-03-20
SELECT TO_CHAR(SYSDATE, 'YY-MM-DD DAY') FROM DUAL;              -- 22-03-20 일요일
SELECT TO_CHAR(SYSDATE, 'YY-MM-DD DAY HH:MI:SS') FROM DUAL;     -- 22-03-20 일요일 03:46:52
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD DAY HH:MI:SS') FROM DUAL;   -- 2022-03-20 일요일 03:48:07
SELECT TO_CHAR(SYSDATE, 'YYYY-FMMM-DD DAY HH:MI:SS') FROM DUAL; --2022-3-20 일요일 3:48:47 공백제거
SELECT TO_CHAR(SYSDATE, 'YYYY-FMMM-DD DAY AM HH:MI:SS') FROM DUAL; -- 2022-3-20 일요일 오후 3:50:0
SELECT TO_CHAR(SYSDATE, 'YYYY"년"-MM"월"-DD"일" DAY') FROM DUAL; -- 2022년-03월-20일 일요일 // 리터럴 추가
SELECT TO_CHAR(SYSDATE, 'YYYY"년"-MM"월"-DD"일" DAY AM HH:MI:SS') FROM DUAL; -- 2022년-03월-20일 일요일 오후 03:55:31


SELECT TO_CHAR(SYSDATE) FROM DUAL;                  -- 22/03/15
SELECT TO_CHAR(SYSDATE, 'HH:MI:SS') FROM DUAL;      -- 08:07:45
SELECT TO_CHAR(SYSDATE, 'AM:HH:MI:SS') FROM DUAL;   -- 오후:08:08:07
SELECT TO_CHAR(SYSDATE, 'PM:HH:MI:SS') FROM DUAL;   -- 오후:08:08:07 // AM PM 아무거나 쓰면됨  
SELECT TO_CHAR(SYSDATE, 'AM:HH24:MI:SS') FROM DUAL; -- 오후:20:10:01
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD DAY AM HH:MI:SS') FROM DUAL;  --2022-03-15 화요일 오후 08:10:50
SELECT TO_CHAR(SYSDATE, 'YYYY-FMMM-DD DAY AM HH:MI:SS') FROM DUAL;--2022-3-15 화요일 오후 8:10:59
-- FM을 적용시키면 뒤에까지 적용되서 공백제거 되서 나온다
-- 01초가 나와야하는데 1초가 나옴
SELECT TO_CHAR(SYSDATE, 'YYYY"년"-MM"월"-DD"일" DAY AM HH:MI:SS') FROM DUAL; -- 2022년-03월-15일 화요일 오전 11:40:48
SELECT TO_CHAR(SYSDATE, 'YYYY"년" MM"월" DD"일" DAY AM HH:MI:SS') FROM DUAL; -- 2022년 03월 15일 화요일 오후 08:15:13
-- 글자 출력
-- 글자처럼 비어있는 자리를 지워주는 역할

-- 보이는게 다른 3가지
SELECT TO_CHAR(SYSDATE,'YYYY') FROM DUAL; -- 2022
SELECT TO_CHAR(SYSDATE,'YY') FROM DUAL; -- 22
SELECT TO_CHAR(SYSDATE,'YEAR')FROM DUAL; -- TWENTY TWENTY-TWO

SELECT TO_CHAR(SYSDATE,'MM')FROM DUAL; -- 03
SELECT TO_CHAR(SYSDATE,'MONTH')FROM DUAL; -- 3월 
SELECT TO_CHAR(SYSDATE,'MON')FROM DUAL; -- 3월 
SELECT TO_CHAR(SYSDATE,'RM')FROM DUAL; -- III 
SELECT TO_CHAR(SYSDATE,'MM'), TO_CHAR(SYSDATE,'MONTH'),
        TO_CHAR(SYSDATE,'MON'), TO_CHAR(SYSDATE,'RM')
FROM DUAL;  -- 03	3월 	3월 	III 


SELECT TO_CHAR(SYSDATE, 'YYYY') FROM DUAL;  -- 2022
SELECT TO_CHAR(SYSDATE, 'YY') FROM DUAL;    -- 22
SELECT TO_CHAR(SYSDATE, 'MM') FROM DUAL;    -- 03
SELECT TO_CHAR(SYSDATE, 'MONTH') FROM DUAL; -- 3월
SELECT TO_CHAR(SYSDATE, 'MON') FROM DUAL;   -- 3월
SELECT TO_CHAR(SYSDATE, 'RM') FROM DUAL;    -- III 
SELECT TO_CHAR(SYSDATE, 'YY-MONTH-RM') FROM DUAL; -- 22-3월 -III 
SELECT TO_CHAR(SYSDATE, 'YY MONTH RM') FROM DUAL; -- 22 3월  III 
SELECT TO_CHAR(SYSDATE, 'DDD'), -- 한 해를 기준으로 몇일이 지나있는가
       TO_CHAR(SYSDATE, 'DD'),  -- 한 달을 기준으로 몇일이 지나있는가
       TO_CHAR(SYSDATE, 'D')    -- 한 주를 기준으로 몇일이 지나있는가(일요일 기준)
FROM DUAL; -- 079	20	1
SELECT TO_CHAR(SYSDATE, 'Q'),   -- Q : 분기를 나타냄. 1-4분기
       TO_CHAR(SYSDATE, 'DAY'), -- DAY : 요일
       TO_CHAR(SYSDATE, 'DY')   -- DY : 요일
FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'Q DAY DDD') FROM DUAL; -- 1 일요일 079

SELECT TO_CHAR(SYSDATE,'DDD'), -- 한달을 기준으로 몇일이 지나있는가
    TO_CHAR(SYSDATE,'DD'), -- 주를 기준으로 몇일이 지나있는가
    TO_CHAR(SYSDATE,'D') -- 한 해를 기준으로 몇일이 지나있는가
FROM DUAL; -- 074	15	3
 
SELECT TO_CHAR(SYSDATE,'Q'), TO_CHAR(SYSDATE,'DAY'), TO_CHAR(SYSDATE,'DY')
FROM DUAL; -- 1	일요일	일
-- Q : 분기를 나타냄. 1-4분기
-- DAY : 요일
-- DY : 요일



--EMPLOYEE테이블에서 이름, 입사일(2022년 03월 15일 (화) 형식) 조회

SELECT EMP_NAME, TO_CHAR(HIRE_DATE, 'YYYY"년" MM"월" DD"일" (DY)') 
FROM EMPLOYEE; -- 선동일	1990년 02월 06일 (화)


FROM EMPLOYEE;



------------------------------------------------------------------------------
------------------------------------------------------------------------------




-- B) TO_DATE
-- 문자/숫자형 데이터를 날짜형 데이터로 변환
--
-- Y : 두자리 연도에 무조건 현재 세기(21세기 , 20XX) 적용
-- R : 두자리 연도가 50이상일 때, 이전 세기(20세기,19XX) 적용
--     두자리 연도가 50미만일 때, 현재 세기(21세기, 20XX) 적용



SELECT TO_DATE('20220315','YYYYMMDD') FROM DUAL; -- 22/03/15
SELECT TO_DATE(20220315,'YYYYMMDD') FROM DUAL; -- 22/03/15
SELECT TO_DATE('20220315','YYYYMMDD') FROM DUAL; -- 22/03/15

-- 입력 받은 문자열 : 20220713을 2022년 07월 13일 형식으로 출력하고 싶다면?
-- 20220713  -> 2022년 07월 13일
-- 문자열을 받는거니 TO_CHAR써서 하면 편하지 않을까? 해서 써보면 에러
-- TO_CHAR는 날짜/숫자형 데이터를 문자형 데이터로 변경하는 함수
-- 아래에서 TO_CHAR()의 첫 매개변수가 숫자가 ' '로 감싸진 문자라서 에러나는 것
-- 문자+문자 더하기 가능한건? EX)TO_CHAR(1234) + TO_CHAR(4321)
-- 문자가 숫자로 바뀌는 문자라면 문제없이 연산처리 가능하도록 오라클은 되어있기에 가능했던 것
-- 자바는 '1234'+'4321'이면 '12344321'이겠지만 오라클은 숫자형식인 문자면 자동형변환해서 연산해준다

SELECT TO_CHAR('20220315','YYYY"년" MM"월" DD"일"') --  ERROR : invalid number format model
FROM DUAL;
-- TO_CHAR()를 쓸려면 '20220315'의 형식 바꿔야함
-- TO_DATE()로 날짜 데이터를 만듬 : SELECT T0_DATE('20220315','YYYYMMDD')

SELECT TO_CHAR('20220315','YYYY"년" MM"월" DD"일"') 
FROM DUAL; --  ERROR : invalid number format model
SELECT TO_CHAR(TO_DATE('20220315','YYYYMMDD'), 'YYYY"년" MM"월" DD"일"')
FROM DUAL; -- 2022년 03월 15일


SELECT TO_CHAR(TO_DATE('220713 175019','YYMMDD HH24MISS'), 'YY-MM-DD AM HH:MI:SS DY')
FROM DUAL; -- 22-07-13 오후 05:50:19 수
-- 데이트는 시간까지 보여주지 않는다. 타임스탬프 써야함

-- TO_DATE()에서의 연도 표시 : YY, RR
-- 연도표시를 YY말고도 RR도 가능. 차이는?
SELECT TO_DATE('980630', 'YYMMDD'),  -- 98/06/30
        TO_DATE('980630', 'RRMMDD'), -- 98/06/30
        TO_DATE('140918', 'YYMMDD'), -- 14/09/18
        TO_DATE('140918', 'RRMMDD')  -- 14/09/18
FROM DUAL; -- 98/06/30	98/06/30	14/09/18	14/09/18
-- TO_DATE() 출력에서는 차이가 없어보인다. TO_CHAR()+TO_DATE()에서는?
SELECT TO_CHAR(TO_DATE('980630', 'YYMMDD'),'YYYYMMDD'),  -- 20980630
        TO_CHAR(TO_DATE('980630', 'RRMMDD'),'YYYYMMDD'), -- 19980630
        TO_CHAR(TO_DATE('140918', 'YYMMDD'),'YYYYMMDD'), -- 20140918
        TO_CHAR(TO_DATE('140918', 'RRMMDD'),'YYYYMMDD')  -- 20140918
FROM DUAL; -- 20980630	19980630	20140918	20140918
-- 앞에있는 천의자리랑 백의자리가 생략되어있어서 그동안 몰랐던 것.
-- TO_CHAR()로 천의자리까지 만들어준 것
-- Y : 두자리 연도에 무조건 현재 세기(21세기 , 20XX) 적용
-- R : 두자리 연도가 50이상일 때, 이전 세기(20세기,19XX) 적용
--     두자리 연도가 50미만일 때, 현재 세기(21세가, 20XX) 적용




-- 문자 -> 날짜
SELECT TO_DATE('20220320','YYYYMMDD') FROM DUAL; -- 22/03/20 
-- 숫자 -> 날짜
SELECT TO_DATE(20220320, 'YYYYMMDD') FROM DUAL;  -- 22/03/20

-- 데이트는 시간까지 보여주지 않는다. 타임스탬프 써야함
-- TO_DATE + TO_CHAR
-- 년,월,일,시간 같은 것들을 붙일려면 TO_CHAR로 감싼다
SELECT TO_CHAR(TO_DATE(20220320,'YYYYMMDD'), 'YYYY"년" MM"월" DD"일"')
FROM DUAL; -- 2022년 03월 20일
SELECT TO_DATE('220713 215005','YYMMDD HH24MISS')
FROM DUAL; -- 22/07/13 // 시간 출력 X
SELECT TO_CHAR(TO_DATE('220713 215005','YYMMDD HH24MISS'), 'YY/MM/DD AM HH:MI:SS DY')
FROM DUAL; -- 22/07/13 오후 09:50:05 수
SELECT TO_CHAR(TO_DATE('220713 175019','YYMMDD HH24MISS'), 'YY-MM-DD AM FMHH:MI:SS DY')
FROM DUAL; -- 22-07-13 오후 5:50:19 수


-- Y와 R의 차이
-- TO_DATE()로만으로는 차이가 없어보인다. TO_DATE()+TO_CHAR()는?
SELECT TO_DATE('000320','YYMMDD'), -- 00/03/20
       TO_DATE('000320','RRMMDD'), -- 00/03/20
       TO_DATE('450625','YYMMDD'), -- 45/06/25
       TO_DATE('450625','RRMMDD')  -- 45/06/25
FROM DUAL;
SELECT TO_CHAR(TO_DATE('900320','YYMMDD'),'YYYY/MM/DD'), -- 2090/03/20
       TO_CHAR(TO_DATE('900320','RRMMDD'),'YYYY/MM/DD'), -- 1990/03/20
       TO_CHAR(TO_DATE('450625','YYMMDD'),'YYYY/MM/DD'), -- 2045/06/25
       TO_CHAR(TO_DATE('450625','RRMMDD'),'YYYY/MM/DD')  -- 2045/06/25
FROM DUAL;

------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- C) TO_NUMBER
-- 문자형 데이터를 숫자형 데이터로 변환
-- TO_NUMBER(변환할 컬럼or문자,'들어온 데이터형식 인식시키는기준')
-- TO_NUMBER('10,000','999,999')

SELECT '1234' CHAR_NUMBER, TO_NUMBER('1234') FROM DUAL;
-- 문자는 왼쪽정렬, 숫자는 오른쪽 정렬

-- CHAR + CHAR 숫자 연산 가능한데 왜 굳이 NUMBER연산해야할까?
--
SELECT '1234'+'4321' FROM DUAL; -- 5555
SELECT '10,000' + '5,000' FROM DUAL; -- ERROR : invalid number
 -- 쉼표 때문에 에러. 사람이 인식하기에 ,는 숫자 자릿수 구분이지만
 --  컴퓨터한테는 쉼표가 붙어 숫자로 인식할 수 없게 된 것
SELECT TO_NUMBER('10,000') FROM DUAL; -- ERROR : invalid number
SELECT TO_NUMBER('10,000','999,999') FROM DUAL; -- 10000
-- 두번째 인자 : 지금 들어온 문자 타입이 이런 형식이라는 것을 인식시키는 기준
SELECT TO_NUMBER('10,000','999,999'), TO_NUMBER('5,000','999,999') FROM DUAL;--10000	5000
SELECT TO_NUMBER('10,000','999,999') + TO_NUMBER('5,000','999,999') FROM DUAL;--15000



SELECT TO_NUMBER('10,000','000,000') -- ERROR: ORA-01722: invalid number
FROM DUAL;                      -- 공백을 0으로 채우면 이상해지니 에러나는듯
SELECT TO_NUMBER('10,000','999,999') -- 10000
FROM DUAL;
-- TO_NUMBER+TO_NUMBER의 산술연산
SELECT TO_NUMBER('5000','999,999') + TO_NUMBER('5000','999,999')
FROM DUAL; -- ORA-01722: invalid number
           -- 에러원인 : 셋째자리에 ,받기로 했는데 ,이 없어서 에러
SELECT TO_NUMBER('5,000','999,999') + TO_NUMBER('5,000','999,999')
FROM DUAL; -- 10000




------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- 5)NULL처리 함수


-- NVL
-- null값을 지정한 값으로 대체하는 함수
--
-- 실제값을 바꾸는건 X
-- 대체할 값은 대체할려는 데이터의 타입을 따라가야한다 
--      ex)bonus의 데이터타입이 number이므로 숫자만가능

-- NULL을 다른 값으로 인지시키게 못하나?로부터 나오게 됨
SELECT EMP_NAME, BONUS, NVL(BONUS, 0) 
FROM EMPLOYEE;
SELECT NVL(BONUS,0) FROM EMPLOYEE;
SELECT NVL(BONUS,100) FROM EMPLOYEE;
SELECT NLV(BONUS, '보너스없음') FROM EMPLOYEE;



SELECT NVL(BONUS, '보너스X') -- ERROR : : invalid number
FROM EMPLOYEE; -- ex)bonus의 데이터타입이 number이므로 숫자만가능

-- NVL2
-- NVL2(컬럼명, NULL이면 이걸로 변경, NULL이 아니면 이걸로 변경)
-- NULL값이 존재한다면 두번째 인자값으로 변경, NULL값이 존재하지 않으면 세번째 인자값으로 변경
-- 해당데이터가 NULL이면 0.7로 아니면 0.5로 대체

SELECT NVL2(BONUS, 0, 100) FROM EMPLOYEE;
SELECT NVL2(BONUS, 50, 100,) FROM EMPLOYEE;
SELECT NVL2(BONUS,0.7,0.5) FROM EMPLOYEE;

-- NULLIF
-- 비교하는 값이 같으면 NULL, 다르면 앞에 있는 값 반환
-- (NULL)	123

SELECT NULLIF(123,123) FROM DUAL; -- 두 비교값이 같아 NULL반환
-- 데이터(컬럼명) 적용
SELECT EMP_NAME, NULLIF(EMPLOYEE.JOB_CODE, JOB.JOB_CODE) FROM EMPLOYEE, JOB;



------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- 6.선택함수

-- DECODE
-- DECODE(계산식|컬럼명, 조건값1, 선택값1, 조건값2, 선택값2, ...)
-- 계산식에 따라 조건값1에 맞으면 선택값1 반환, 조건값2에 맞으면 선택값2를 반환하는 함수
-- 범위를 다루는 >,< 같은 것들은 DECODE로 쓸 수 없다
-- JAVA SWITCH 스위치도 딱딱 수가 떨어지는 것만 가능

-- 주민번호 옆에 성별 같이 찍히도록 해볼 것
SELECT EMP_ID, EMP_NAME, EMP_NO,
        DECODE(SUBSTR(EMP_NO,8,1),1,'남',2,'여') 성별
FROM EMPLOYEE;
        

-- 직원의 급여를 인상하고자 한다
-- 직급코드가 J7인 직원은 급여의 10%를 인상하고
-- 직급코드가 J6인 직원은 급여의 15%를 인상하고
-- 직급코드가 J5인 직원은 급여의 20%를 인상하며
-- 그 외 직급의 직원은 급여의 5%만 인상한다
-- 직원 테이블에서 직원명, 직급코드, 급여, 인상급여(위 조건)을 조회

SELECT EMP_NAME, JOB_CODE, SALARY, 
        DECODE(JOB_CODE,'J7',SALARY*1.1,'J6',SALARY*1.15,'J5',SALARY*1.2,SALARY*1.05) 인상급여
FROM EMPLOYEE;

------------------------------------------------------------------------------


-- CASE ~ WHEN ~ THEN
-- CASE WHEN 조건식THEN 결과값
--      WHEN 조건식THEN 결과값
--      ELSE 결과값
-- END

-- 주민번호 + 성별 출력
SELECT EMP_NAME, EMP_NO,
        DECODE(SUBSTR(EMP_NO,8,1),1,'남',2,'여')
FROM EMPLOYEE;


-- 직원의 급여를 인상하고자 한다
-- 직급코드가 J7인 직원은 급여의 10%를 인상하고
-- 직급코드가 J6인 직원은 급여의 15%를 인상하고
-- 직급코드가 J5인 직원은 급여의 20%를 인상하며
-- 그 외 직급의 직원은 급여의 5%만 인상한다
-- 직원 테이블에서 직원명, 직급코드, 급여, 인상급여(위 조건)을 조회
SELECT EMP_NAME, JOB_CODE, SALARY,
        CASE WHEN JOB_CODE = 'J7' THEN SALARY*1.1
             WHEN JOB_CODE = 'J6' THEN SALARY*1.15
             WHEN JOB_CODE = 'J5' THEN SALARY*1.2
             ELSE SALARY*1.05
        END  "인상급여"
FROM EMPLOYEE;

-- 위와 같은 코드
-- CASE 공통된컬럼명 WHEN 조건식 THEN 결과
SELECT EMP_NAME, JOB_CODE, SALARY,
        CASE JOB_CODE WHEN 'J7' THEN SALARY*1.1
                      WHEN 'J6' THEN SALARY*1.15
                      WHEN 'J5' THEN SALARY*1.2
                      ELSE SALARY*1.05
        END "인상급여"
FROM EMPLOYEE;


-- 사번, 사원명, 급여, 등급조회
-- 등급 조건 : 급여가 500만보다 크면 1등급, 350만보다 크면 2등급, 200만보다 크면 3등급, 나머지는 4등급
-- DECODE로도 가능?
-- 범위를 다루는 >,< 같은 것들은 DECODE로 쓸 수 없다
-- JAVA SWITCH 스위치도 딱딱 수가 떨어지는 것만 가능
SELECT EMP_ID, EMP_NAME, SALARY,
        CASE WHEN SALARY> 5000000 THEN '1등급'
             WHEN SALARY> 3500000 THEN '2등급'
             WHEN SALARY> 2000000 THEN '3등급'
             ELSE '4등급'
        END "등급조회"
FROM EMPLOYEE;  -- 200	선동일	8000000	1등급

-- ERROR : 축약에러
SELECT EMP_ID, EMP_NAME, SALARY,
        CASE SALARY WHEN > 5000000 THEN '1등급' -- ERROR : 축약에러
                    WHEN > 3500000 THEN '2등급' -- ORA-00936: missing expression
                    WHEN > 2000000 THEN '3등급'
                    ELSE '4등급'
        END "등급조회"
FROM EMPLOYEE;



------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
---------------------------------- 그룹 함수 ----------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- 그룹 함수


-- SUM
-- 총합계
-- EMPLOYEE테이블에서 전 사원의 급여 총합

SELECT SUM(SALARY) FROM EMPLOYEE;

-- EMPLOYEE테이블에서 남자사원의 급여 총합
SELECT SUM(SALARY)
FROM EMPLOYEE
WHERE SUBSTR(EMP_NO,8,1) = 1;


-- AVG
-- 평균
-- EMPLOYEE테이블에서 전 사원의 급여 평균
 -- 3047662.60869565217391304347826086956522
 SELECT AVG(SALARY) FROM EMPLOYEE;
 
-- EMPLOYEE테이블에서 여자사원의 급여 총합
-- 2542030
SELECT AVG(SALARY)
FROM EMPLOYEE
WHERE SUBSTR(EMP_NO,8,1) = 2;

-- EMPLOYEE테이블에서 전 사원의 보너스 평균
-- BONUS가 NULL인 사원은 0으로 처리
-- 0.0847826086956521739130434782608695652174
-- SUM(BONUS)/23

SELECT AVG(NVL(BONUS,0))
FROM EMPLOYEE;




-- 0.2166666666666666666666666666666666666667
-- NULL을 가진 값은 평균 계산에서 제외되어 계산
-- SUM(BONUS)/9
SELECT AVG(BONUS)
FROM EMPLOYEE; -- 0.2166666666666666666666666666666666666667
SELECT SUM(BONUS)/9
FROM EMPLOYEE; -- 0.2166666666666666666666666666666666666667
SELECT SUM(BONUS)/23
FROM EMPLOYEE; -- 0.0847826086956521739130434782608695652174


-- MIN / MAX
-- 최소 / 최대
-- 숫자, 날짜, 문자도 가능
-- EMPLOYEE테이블에서 최소 급여와 최대 급여
-- 8000000	1380000
SELECT MAX(SALARY), MIN(SALARY) FROM EMPLOYEE; -- 8000000	1380000



-- 문자 넣기
SELECT MAX(EMP_NAME), MIN(EMP_NAME) FROM EMPLOYEE;
-- 날짜 넣기
SELECT MAX(HIRE_DATE), MIN(HIRE_DATE) FROM EMPLOYEE;


-- COUNT
-- NULL값은 제외하고 카운트
-- 23
-- 직원 23명 카운트함
SELECT COUNT(*) FROM EMPLOYEE; -- 전체 자료수를 카운트하는 듯


-- 21
-- NULL 2명을 제외한 21 반환
SELECT COUNT(DEPT_CODE) FROM EMPLOYEE;  -- 21

 

 

728x90
반응형
728x90



728x90
반응형

'small steps > 운동 - 체력이 국력' 카테고리의 다른 글

22.03.23 운동기록 - 어깨 집중 중  (0) 2022.03.23
22.03.20 운동기록  (0) 2022.03.20
22.03.15 운동기록  (0) 2022.03.16
22.03.12 운동기록  (0) 2022.03.13
22.03.11 운동기록  (0) 2022.03.12
728x90

SUBSTR, REPLACE

FLOOR/TRUNC, 

MOD, 

 

SYSDATE, 

MONTHS_BETWEEN, ADD_MONTHS,

NEXT_DAY, LAST_DAY, EXTRACT

--SUBSTR
-- String.substring()
--SUBSTR(컬럼명, 시작위치 인덱스, 시작위치부터 값을 반환할 길이)


-- HELLOMYGOODFRIENDS // YGOODFRIENDS
-- 7번째서부터 끝까지 반환
SELECT SUBSTR('HELLOMYGOODFRIENDS',7) FROM DUAL;

-- HELLOMYGOODFRINEDS // OM
-- 5번째 문자부터 2개만 반환
SELECT SUBSTR('HELLOMYGOODFRIENDS',5,2) FROM DUAL;

-- HELLOMYGOODFRINEDS // (null)
-- 5번쨰 문자부터 0개 반환 // 0개 반환이 불가능하기에 NULL 출력됨
SELECT SUBSTR('HELLOMYGOODFRIENDS',5,0) FROM DUAL; -- --(NULL)
-- HELLOMYGOODFRINEDS // HELLOM
SELECT SUBSTR('HELLOMYGOODFRIENDS',0,5) FROM DUAL; -- HELLO // 0부터 시작해도 1부터 적용
SELECT SUBSTR('HELLOMYGOODFRIENDS',1,5) FROM DUAL; -- HELLO // 0부터 시작해도 1부터 적용


-- HELLOMYGOODFRINEDS //  DFR
-- 뒤에서 8번째(D)부터 오른쪽으로 3개의 문자 반환
-- 위에서 마이너스(-)였으면 기준점이 뒤에서부터 세고 왼쪽방향으로 카운팅했지만 얘는 오른쪽으로 카운팅
SELECT SUBSTR('HELLOMYGOODFRIENDS',-8,3) FROM DUAL; -- DFR
-- HELLOMYGOODFRINEDS // OO
SELECT SUBSTR('HELLOMYGOODFRIENDS',-10,2) FROM DUAL;  -- OO
SELECT SUBSTR('HELLOMYGOODFRIENDS',-10,-2) FROM DUAL; -- 3RD 인자 몇번째문자인지가 -이면 NULL값


-- EMPLOYEE 테이블에서 이름, 이메일, 이메일의 아이디 조회
-- (이메일의 @ 도메인말고 아이디까지만)
SELECT EMP_NAME, EMAIL, SUBSTR(EMAIL,1,INSTR(EMAIL,'@')-1)
FROM EMPLOYEE;
-- 문제풀이 사고과정
-- 1.이메일 아이디의 규칙은 항상 @이 앞에 있음
-- 2. @ 위치 파악
-- 3. 1~@앞까지 찾기

-- EMPLOYEE 테이블에서 이름, 이메일, 이메일의 아이디 조회
-- (이메일의 @ 도메인말고 아이디까지만)
SELECT EMP_NAME, EMAIL,SUBSTR(EMAIL,1,INSTR(EMAIL,'@')-1)
FROM EMPLOYEE;


-- 주민등록번호를 이용하여 이름과 성별을 나타내는 부분 조회
-- EMPLOYEE 테이블에서 남자만 조회(사원명, '남')
-- EMPLOYEE 테이블에서 여자만 조회(사원명, '여')
SELECT EMP_NAME 사원명, CASE WHEN SUBSTR(EMP_NO,8,1)=1 THEN '남'
                            WHEN SUBSTR(EMP_NO,8,1)=2 THEN '여'
                       END 성별 
FROM EMPLOYEE;

SELECT EMP_NAME 사원명, DECODE(SUBSTR(EMP_NO,8,1),1,'남',2,'여') 성별
FROM EMPLOYEE;



-- EMPLOYEE테이블에서 직원들의 주민번호를 이용하여 사원명, 생년, 생월, 생일 조회
SELECT EMP_NAME 사원명,  SUBSTR(EMP_NO,1,2) 생년, SUBSTR(EMP_NO,3,2) 생월, SUBSTR(EMP_NO,5,2) 생일
FROM EMPLOYEE;



------------------------------------------------------------------------------
------------------------------------------------------------------------------


-- LOWER / UPPER / INITCAP
-- INITCAP :각 단어의 첫글자만 대문자

-- 예제 Welcome To my World
-- welcome to my world
SELECT LOWER('Welcome To my World') FROM DUAL;
-- WELCOME TO MY WORLD
SELECT UPPER('Welcome To my World') FROM DUAL;
-- Welcome To My World
SELECT INITCAP('Welcome To my World') FROM DUAL;


------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- CONCAT
-- 문자열 이어붙이기

-- 가나다라123
SELECT CONCAT('가나다라','123') FROM DUAL;
SELECT CONCAT(DEPT_CODE, '-333') FROM EMPLOYEE; -- D9-333
SELECT CONCAT(JOB_CODE, ' BY S') FROM JOB; -- J1 BY S
SELECT CONCAT(DEPT_CODE, JOB_CODE) FROM EMPLOYEE; -- D9J1
-- 연결연산자 사용 : 가나다라123
-- 연결연산자 : ||
SELECT '가나다라' || '123' FROM DUAL; -- 가나다라123


------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- REPLACE
-- REPLACE(컬럼명,바꿔질 단어, 바꿀 단어)
-- 값 교체

-- 서울시 강남구 역삼동 // 서울시 강남구 삼성동
SELECT REPLACE('서울시 강남구 역삼동','역삼동','삼성동') FROM DUAL;

-- 강사님은 오라클을 수업중이다 // 선생님은 오라클을 수업중이다
-- 띄어쓰기 상관없이 적용가능
SELECT REPLACE('강사님은 오라클을 수업중이다','강사님','선생님') FROM DUAL;

-- 케이크 달다. 케이크 싫은사람? // 공부 달다. 공부 싫은사람?
-- 여러개 들어있어도 복수로 교체가능. 일치만 하면 전부 교체함
SELECT REPLACE('케이크 달다. 케이크 싫은사람?','케이크','단 거') FROM DUAL;

-- EMPLOYEE테이블에서 사원명, 주민번호 조회
-- 주민번호의 뒷자리는 *로 바꿔서 조회(EX.001122-*******)


-- REPLACE+SUBSTR

-- REPLACE+SUBSTR+INSTR


/*
REPLACE(EMP_NO,SUBSTR(EMP_NO,8,14/2)
SELECT REPLACE(EMP_NO,SUBSTR(EMP_NO,8,14/2)) FROM EMPLOYEE;
SELECT REPLACE(EMP_NO,SUBSTR(EMP_NO,8,LENGTH(EMP_NO)/2)) FROM EMPLOYEE;
SELECT LENGTH(EMP_NO)/2 FROM EMPLOYEE;
*/

-- RPAD+SUBSTR
SELECT EMP_NAME, RPAD(SUBSTR(EMP_NO,1,7),14,'*******')
FROM EMPLOYEE;


-- 방법1
-- REPLACE+SUBSTR 끝수 지정 & 미지정 


-- 방법2
-- RPAD+SUBSTR
SELECT EMP_NAME, REPLACE(EMP_NO,SUBSTR(EMP_NO,8,7),'*******') 주민번호
FROM EMPLOYEE;

-- RPAD+SUBSTR+INSTR
SELECT EMP_NAME, REPLACE(EMP_NO,SUBSTR(EMP_NO,8,7),'*******')
FROM EMPLOYEE;

-- RPAD+SUBSTR+INSTR+LENGTH
SELECT EMP_NAME, REPLACE(EMP_NO,SUBSTR(EMP_NO,INSTR(EMP_NO,'-')+1,LENGTH(EMP_NO)/2),'*******')
FROM EMPLOYEE;

-- 방법3
-- REPLACE+SUBSTR+INSTR+LENGTH


-- 방법4
-- SUBSTR+연결연산자(||)
SELECT EMP_NAME, SUBSTR(EMP_NO, 1, 7) || '*******' 주민번호
FROM EMPLOYEE;



------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------

-- 2) 숫자 관련 함수


-- ABS
-- 절대값 반환
SELECT ABS(FLOOR(1.234)) FROM DUAL;
-- 10.9	10.9	10	10
-- 전부 양수 출력
SELECT ABS(-10.9), ABS(10.9), ABS(-10) FROM DUAL;

-- MOD
-- 모듈러
-- 나머지 구하기
-- MOD(나눠지는수 ,나누는 수)

-- 1	-1	1	-1	1.9
-- 내가 나누어지는 수에 대한 부호를 따라가게 됨
SELECT MOD(10,3), MOD(-10,3), MOD(10,-3), MOD(-10,-3), MOD(10.9,3) FROM DUAL;


-- ROUND
-- 몇번째 자리에서 반올림할지 소수점 자리수 지정가능
-- 123.456
-- 123	124	123	123.5	123.46	120	100
-- 소수점 자리지정 반올림
-- 소수점 -의 반올림
SELECT ROUND(123.456,0),ROUND(123.456), ROUND(123.456,1),ROUND(123.456,2), ROUND(123.456,-1) FROM DUAL;
SELECT ROUND(123.456,-1), ROUND(123.456,-2) FROM DUAL;

-- -11
-- 마이너스(-)의 반올림은?
-- 마이너스는 숫자가 클수록 작은 수 ex) -11이 -10보다 작은 수
-- -10.61에서 .61이 5이상이라 반올림이 되는데 -11로



-- CEIL
-- 124
-- 무조건 1의 자리에서 올림하게 되어있음
-- 자릿수 지정 불가. 다른 인자값 집어넣으면 에러
SELECT CEIL(123.456) FROM DUAL;


-- FLOOR / TRUNC
-- FLOOR : 수학적 내림(배웠던 수학의 내림) // 자릿수 지정 불가
-- TRUNC : 버림. 절삭. 몇번째 자리까지 버리겠다 // 자릿수 지정가능
SELECT FLOOR(123.456), TRUNC(123.456) FROM DUAL;
SELECT FLOOR(123.456), TRUNC(123.456,1) FROM DUAL;

-- 123	123	123.7
-- TRUNC : 몇번째 자리까지 버리겠다 자릿수 지정가능
-- 파이썬에서 FLOOR가 -쪽으로 내리고 TRUNC가 0쪽으로 수렴하는 것과 같은 개념
-- math.trunc(-3.14)   #결과는 -3
-- math.floor(-3.14)   #결과는 -4






------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------



-- 3)날짜 관련 함수

-- SYSDATE
-- 시스템에 저장되어있는 시간을 사용

SELECT SYSDATE FROM DUAL; -- 22/03/14



-- MONTHS_BETWEEN
-- ex) MONTHS_BETWEEN(SYSDATE, HIRE_DATE)
-- 개월수의 차를 숫자로 리턴해주는 함수
SELECT MONTHS_BETWEEN(SYSDATE, HIRE_DATE) FROM EMPLOYEE; -- 385일 차이
SELECT SYSDATE,HIRE_DATE, MONTHS_BETWEEN(SYSDATE, HIRE_DATE) FROM EMPLOYEE;
SELECT SYSDATE,HIRE_DATE, ABS(MONTHS_BETWEEN(SYSDATE, HIRE_DATE)) FROM EMPLOYEE;


-- EMPLOYEE테이블에서 사원의 이름, 입사일, 근무 개월 수 조회
SELECT EMP_NAME, HIRE_DATE, MONTHS_BETWEEN(SYSDATE,HIRE_DATE) "근무 개월 수"
FROM EMPLOYEE;

SELECT EMP_NAME, HIRE_DATE, CEIL(ABS(MONTHS_BETWEEN(HIRE_DATE, SYSDATE))) || '개월차'
FROM EMPLOYEE; -- 368개월차
-- 앞뒤로 뭐가 올지 모른다면 ABS를 넣어서 절대값으로 받아오면 된다

SELECT EMP_NAME, HIRE_DATE, CEIL(MONTHS_BETWEEN(SYSDATE,HIRE_DATE)) || '일수'"근무일수" FROM EMPLOYEE;




-- ADD_MONTHS
-- 기준 날짜에다 지정한 숫자만큼의 개월수로 더한 날짜 리턴
SELECT ADD_MONTHS(SYSDATE,4) FROM EMPLOYEE; -- 22/07/19
-- 지금부터 4개월 뒤 반환
SELECT ADD_MONTHS(SYSDATE,12) FROM EMPLOYEE; -- 23/03/19
-- 개월수가 더해져서 연도가 넘어가면 연도도 올라감

--EMPLOYEE테이블에서 사원의 이름, 입사일, 입사 후 6개월이 된 날짜 조회
SELECT EMP_NAME, HIRE_DATE, ADD_MONTHS(HIRE_DATE,6) FROM EMPLOYEE;
SELECT EMP_NAME, ADD_MONTHS('00/01/01',12) FROM EMPLOYEE; -- 01/01/01
-- 마이너스 -12개월
SELECT EMP_NAME, ADD_MONTHS('00/01/01',-12) FROM EMPLOYEE; -- 99/01/01



-- NEXT_DAY
-- 기준 날짜에서 구하려는 요일에 가장 가까운 날짜 리턴
-- 1=일, 2=월, 3=화,4=수, 5=목, 6=금, 7=토
-- 텍스트의 맨 앞글자만 따와서 요일 반환

SELECT SYSDATE, NEXT_DAY(SYSDATE, '일') FROM DUAL; -- 22/03/19	22/03/20
SELECT SYSDATE, NEXT_DAY(SYSDATE, '토') FROM DUAL; -- 22/03/19	22/03/26

-- 지금 기준으로부터 가장 가까운 목요일 구하기
SELECT NEXT_DAY(SYSDATE, '목') FROM DUAL;    -- 22/03/24
SELECT NEXT_DAY(SYSDATE, '목요일') FROM DUAL; -- 22/03/24
SELECT NEXT_DAY(SYSDATE, 5) FROM DUAL;       -- 22/03/24   
-- 1=일, 2=월, 3=화,4=수, 5=목, 6=금, 7=토
SELECT NEXT_DAY(SYSDATE, 'THUR') FROM DUAL; -- ERROR :  not a valid day of the week



SELECT SYSDATE, NEXT_DAY(SYSDATE, '목성주기') FROM DUAL; -- 22/03/19	22/03/24
-- 요일과 관련 없는 단어지만 맨 앞글자 '목'만 따서 요일 반환하는 걸 알 수 있다
SELECT SYSDATE, NEXT_DAY(SYSDATE, '금성') FROM DUAL; -- 22/03/19	22/03/25
-- 금성의 맨 앞글자 '금' = 금요일


-- 한글만 인지하게끔 설정이 되어있어 인식오류 뜨는 것

-- 영어로 세팅
ALTER SESSION SET NLS_LANGUAGE = AMERICAN; -- Session이(가) 변경되었습니다.
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURSDAY') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURSTY') FROM DUAL; -- 22/03/15	22/03/17
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR--') FROM DUAL; -- 22/03/15	22/03/17
-- 한글과 동일하게 앞글자만 맞으면 요일 반환. 아마도 첫발음의 한글자를 치는 듯

SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THURDAY') FROM DUAL; -- 22/03/19	22/03/24
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR') FROM DUAL;    -- 22/03/19	22/03/24
SELECT SYSDATE, NEXT_DAY(SYSDATE, 'THUR---') FROM DUAL;


-- 한글로 세팅
ALTER SESSION SET NLS_LANGUAGE = KOREAN; -- Session이(가) 변경되었습니다.

SELECT NEXT_DAY(SYSDATE, '금') FROM DUAL; -- 22/03/25
SELECT NEXT_DAY(SYSDATE, '금성') FROM DUAL;


-- LAST_DAY
-- 해당 날짜의 월의 마지막 일 반환
SELECT LAST_DAY(SYSDATE) FROM DUAL; -- 22/03/31
SELECT LAST_DAY(HIRE_DATE) FROM EMPLOYEE; -- 90/02/28 01/09/30
SELECT LAST_DAY(JOB_CODE) FROM EMPLOYEE; -- ERROR
-- ORA-01841: (full) year must be between -4713 and +9999, and not be 0


-- EXTRACT
-- 년, 월, 일 정보 추출 반환
-- 시간은 추출 불가

SELECT EXTRACT(SYSDATE-hire_date) FROM EMPLOYEE;

SELECT EXTRACT(YEAR FROM SYSDATE), EXTRACT(MONTH FROM SYSDATE),
       EXTRACT(DAY FROM SYSDATE) FROM EMPLOYEE; -- 2022	3	19
SELECT EXTRACT(DAY FROM SYSDATE)
--        EXTRACT(HOUR FROM SYSDATE),  -- 시간은 추출 불가
--        EXTRACT(MINUTE FROM SYSDATE) 
FROM EMPLOYEE;
       
-- EMPLOYEE테이블에서 사원의 이름, 입사연도, 입사월, 입사일 조회

SELECT EMP_NAME, EXTRACT(YEAR FROM HIRE_DATE) 입사연도,
                 EXTRACT(MONTH FROM HIRE_DATE) 입사월, 
                 EXTRACT(MONTH FROM HIRE_DATE) 입사일
FROM EMPLOYEE; -- 선동일	1990	2	2


-- EMPLOYEE테이블에서 사원의 이름, 입사일, 근무년수 조회
-- 단, 근무년수는 현재연도 - 입사연도로 조회
SELECT EMP_NAME,HIRE_DATE, SYSDATE,
        EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM HIRE_DATE) 근무년수
FROM EMPLOYEE; -- 선동일	90/02/06	22/03/19	32

 

 

728x90
반응형
728x90

 

로그인 코드 연습

 

public class practice_everyday03 {

	public static void main(String[] args) {

		// 전체 유저 목록
		// 현재유저 아이디 암호 입력
		// 유저 목록에 있는 체크(반복문)
		// 로그인 완료 메세지
		
		String[][] users_all = {
				{"choi","1111"},
				{"kim","2222"},
				{"lee","3333"}
		};
		String[][] user_current = {
				{args[0]},
				{args[1]} // id pw 따로 받아야하나?		
		};
		
		
		boolean userLogin = false;
		for (int i = 0; i < users_all.length; i++) { // 2차원 배열이지만 안에 배열 갯수를 세온다
//			System.out.println(users_all[i][0]);
//			System.out.println(users_all[i][1]);
//			System.out.println(user_current[i]); // 디버깅 중 출력값 무엇?? [Ljava.lang.String;@6504e3b2 ??
												// current의 배열길이는 전체 두개인데 i변수는 all의 길이이므로 인덱스번호가 안맞아서 오류
//			String[] user_current_IdPw = user_current;
//			if (user_current_IdPw[0].equals(users_all[i][0]) && // 계속 로그인실패만 뜨는데 뭐가 문제지?
//				user_current_IdPw[1].equals(users_all[i][1])	
//						) {
//			if (user_current[0].equals(users_all[i][0]) &&  // 계속 로그인실패만 뜨는데 뭐가 문제지?
//				user_current[1].equals(users_all[i][1])		
//					) {
				userLogin = true;
				break;
			};
//		};
			
		
		if (userLogin) {
			System.out.printf("로그인 성공%n환영합니다");
		} else {
			System.out.println("로그인 실패");
		}
		
	}

}

 

 

728x90
반응형
728x90


728x90
반응형

'small steps > 운동 - 체력이 국력' 카테고리의 다른 글

22.03.20 운동기록  (0) 2022.03.20
22.03.17 운동기록  (0) 2022.03.17
22.03.12 운동기록  (0) 2022.03.13
22.03.11 운동기록  (0) 2022.03.12
22.03.10 운동기록  (0) 2022.03.11

+ Recent posts