DESCRIBE DUAL;
SELECT DUMMY
FROM DUAL;
SELECT '100', TO_NUMBER('100')
FROM DUAL;
SELECT '1.5', TO_NUMBER('1.5')
FROM DUAL;
- 숫자와 '문자' 연산은 오라클에 의해서 숫자와 숫자 연산으로 수정된 뒤 처리됨
▶ '문자' -> TO_NUMBER('문자') 방식으로 자동으로 처리함
SELECT 1+'1'
FROM DUAL;
▶ '문자'와 '문자' 연산도 모두 숫자로 바꿔서 처리
SELECT '1' + '1'
FROM DUAL;
SELECT
TO_CHAR(1234) -- '1234'
,TO_CHAR (1234,'999999') -- ' 1234'
,TO_CHAR (1234, '000000') -- '001234'
,TO_CHAR (1234,'9,999') -- '1,234'
,TO_CHAR (12345,'9,999') -- ###### ( 4자리로 지정하였으나 값은 5자리이기 때문에 표시할 수 없음)
,TO_CHAR (12345,'99,999') -- '12,345'
,TO_CHAR (1.4, '9') -- '1' 형식은 정수 1자리 표기(소수 이하 반올림)
,TO_CHAR (1.5, '9') -- '2' 형식은 정수 1자리 표기(소수 이하 반올림)
,TO_CHAR (0.123, '0.00') -- '0.12', 소수 이하 2자리 표기(반올림)
,TO_CHAR (0.129, '0.00') -- '0.13', 소수 이하 2자리 표기(반올림)
FROM
DUAL;
SELECT
SYSDATE
,SYSTIMESTAMP
FROM DUAL;
//
SELECT
TO_CHAR(SYSDATE,'YYYY-MM-DD') -- YY/MM/DD 형식으로 표시하지만 시간 데이터도 가지고 있음
,TO_CHAR(SYSDATE,'HH:MI:SS')
FROM
DUAL;
SELECT
TO_DATE ('05/06/07', 'YY/MM/DD')
,TO_DATE ('05/06/07', 'MM/DD/YY')
FROM
DUAL;
//
SELECT SYSDATE FROM DUAL;
▶ 사원 테이블에서 90/01/01~99/12/31 사이에 입사한 사원 조회하기
SELECT EMP_NO, NAME , DEPART, POSITION, GENDER, HIRE_DATE, SALARY
FROM EMPLOYEE
WHERE TO_DATE(HIRE_DATE, 'YY/MM/DD') BETWEEN TO_DATE('90/01/01', 'YY/MM/DD') AND TO_DATE ('31/12/99', 'DD/MM/YY');
▶ DT1과 DT2 칼럼에 현재 날짜 넣기
CREATE TABLE SAMPLE(
DT1 DATE,
DT2 TIMESTAMP,
DT3 VARCHAR2(10 BYTE)
--
INSERT INTO
SAMPLE (DT1,DT2,DT3)
VALUES(SYSDATE,SYSTIMESTAMP,TO_CHAR(SYSDATE,'YYYY/MM/DD'));
SELECT DT1,DT2,DT3 FROM SAMPLE;
SELECT DT1,DT2,DT3
FROM SAMPLE
WHERE DT1 = TO_DATE('22/08/26', 'YY/MM/DD');
SELECT DT1,DT2,DT3
FROM SAMPLE
WHERE DT1 = '22/08/26';
SELECT DT1,DT2,DT3
FROM SAMPLE
WHERE TO_DATE(DT1,'YY/MM/DD') = TO_DATE('22/08/26','YY/MM/DD');
NULL값이 연산에서 사용되면 결과는 NULL이다.
▶ NAME이 없으면 '아무개', KOR,ENG,MATH가 없으면 0으로 조회
SELECT
NVL(NAME, '아무개') AS STU_NAME
,NVL(KOR,0)
,NVL(ENG,0)
,NVL(MATH,0)
FROM
SAMPLE
WHERE
STU_NAME != '아무개'
ORDER BY
STU_NAME ASC;
▶ 이름과 총점을 조회하기 (이름이 없으면 '아무개', 점수가 없으면 0점 처리)
SELECT
NVL(NAME,'아무개') AS 이름
,NVL(KOR,0) + NVL(ENG,0) + NVL(MATH,0) AS 총점
FROM
SAMPLE;
SELECT
NVL2 (NAME, NAME || '님', '아무개') -- || ->문자열 연결 연산자 , CONCAT
,NVL2 (KOR, '응시', '결시')
,NVL2(ENG, '응시', '결시')
,NVL2(MATH,'응시', '결시')
FROM
SAMPLE;
▶ 각 칼럼 (KOR, ENG, MATH)의 합계
SELECT
SUM(KOR)
,SUM(ENG)
,SUM(MATH)
,SUM(KOR + ENG + MATH)
,SUM(KOR) + SUM(ENG) + SUM(MATH)
FROM
SAMPLE;
-- 300으로 값은 동일하다
SUM(KOR, ENG, MATH)
→ 오류 : 인수 (ARGUMENTS)가 3개이므로 불가능함
SUM(KOR + ENG + MATH)
→ KOR + ENG + MATH 와 같은 연산 (SUM 함수를 잘못 사용한 예시) ROW단위에서는 SUM을 사용할 수 없다. SUM은 세로단위로 계산을 위함
▶ 각 칼럼 (KOR, ENG, MATH)의 평균
SELECT
AVG(KOR) -- NULL 제외한 KOR의 평균
,AVG(ENG) -- NULL 제외한 ENG의 평균
,AVG(MATH) -- NULL 제외한 MATH의 평균
FROM
SAMPLE;
NULL 값은 결시를 의미하므로 0점 처리함
SELECT
AVG(NVL(KOR,0))
,AVG(NVL(ENG,0))
,AVG(NVL(MATH,0))
FROM
SAMPLE;
▶ 각 칼럼 (KOR, ENG, MATH)의 최대값
SELECT
MAX(KOR)
,MAX(ENG)
,MAX(MATH)
FROM
SAMPLE;
▶ 각 칼럼 (KOR, ENG, MATH)의 최소값
NULL값은 결시를 의미하므로 0점 처리함
SELECT
MIN(NVL(KOR,0))
,MIN(NVL(ENG,0))
,MIN(NVL(MATH,0))
FROM
SAMPLE;
▶ 국어 시험을 응시한 학생이 몇 명인가?
SELECT
COUNT (KOR)
FROM
SAMPLE;
▶ 전체 학생은 몇 명인가? ( 전체 ROW의 개수 )
특정 칼럼을 지정하지 않고 전체 칼럼 (*)을 이용해서 전체 ROW 개수를 구함
SELECT
COUNT(*)
FROM
SAMPLE;
▶-- 성명 국어 영어 수학 합계 평균
-- 아무개 100 100 100 300 100
-- 영숙 0 100 100 200 66.67
-- 정수 100 0 100 200 66.67
-- 지영 100 100 0 200 66.67
SELECT
NVL(NAME,'아무개') AS 성명
,NVL(KOR,0) AS 국어
,NVL(ENG,0) AS 영어
,NVL(MATH,0) AS 수학
,NVL(KOR,0) + NVL(ENG,0) + NVL(MATH,0) AS 합계
,(NVL(KOR,0) + NVL(ENG,0) + NVL(MATH,0)) / 3 AS 평균
FROM
SAMPLE;
SELECT POWER (2,10) FROM DUAL;
SELECT SQRT(25) FROM DUAL;
SELECT ABS(5), ABS(-5) FROM DUAL;
SELECT MOD(7,2) FROM DUAL;
SELECT SIGN(5), SIGN(-5), SIGN(0) FROM DUAL;
SELECT CEIL(1.1), CEIL(-1.1) FROM DUAL;
SELECT FLOOR(1.1), FLOOR(-1.1) FROM DUAL;
SELECT
TRUNC(1.9999) -- 1
,TRUNC(1.9999, 1) -- 1.9
,TRUNC(1.9999, 2) -- 1.99
FROM
DUAL;
SELECT
TRUNC(9999, -1) -- 9990 (원 단위 절사)
,TRUNC(9999, -2) -- 9900
FROM
DUAL;
SELECT
ROUND(145.45) -- 145
,ROUND(145.45, 1) -- 145.5
,ROUND(145.45, -1) -- 150
FROM
DUAL;
SELECT
CEIL(1.111 * POWER(10,1)) / POWER(10,1) -- 1.2
,CEIL(1.111 * POWER(10,2)) / POWER(10,2) -- 1.12
,CEIL(11111* POWER(10,-1)) / POWER(10,-1) -- 11120
,CEIL(11111* POWER(10,-2)) / POWER(10,-2) -- 11200
FROM
DUAL;
SELECT SYSDATE, SYSTIMESTAMP FROM DUAL;
SELECT
TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:MI:SS') -- 12시간
,TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') -- 24시간
FROM
DUAL;
EXTACT (단위 FROM 날짜)
SELECT
EXTRACT(YEAR FROM SYSDATE) AS 년도
,EXTRACT(MONTH FROM SYSDATE) AS 월
,EXTRACT(DAY FROM SYSDATE) AS 일
,EXTRACT(HOUR FROM SYSTIMESTAMP) AS 시 -- UTC 기준
,EXTRACT(MINUTE FROM SYSTIMESTAMP) AS 분
,EXTRACT(SECOND FROM SYSTIMESTAMP) AS 초
,EXTRACT(TIMEZONE_HOUR FROM SYSTIMESTAMP) AS 시 -- 우선 TIMEZONE 설정이 필요
,FLOOR(EXTRACT(SECOND FROM SYSTIMESTAMP)) AS 초
FROM
DUAL;
SELECT
TO_CHAR(SYSDATE,'YYYY')
,TO_CHAR(SYSDATE,'MM')
,TO_CHAR(SYSDATE,'DD')
,TO_CHAR(SYSDATE,'HH24')
,TO_CHAR(SYSDATE,'MI')
,TO_CHAR(SYSDATE,'SS')
FROM
DUAL;
ADD_MONTHS(날짜, N)
SELECT
ADD_MONTHS(SYSDATE, -1) AS "1개월전"
,ADD_MONTHS(SYSDATE, 1) AS "1개월후"
FROM
DUAL;
MONTHS_BETWEEN(최근날짜, 이전날짜) : 두 날짜 사이의 경과한 개월 수
SELECT
MONTHS_BETWEEN(SYSDATE, HIRE_DATE)
FROM
EMPLOYEE;
SELECT
,UPPER(EMAIL)
,LOWER(EMAIL)
,INITCAP(EMAIL)
FROM
EMPLOYEES;
▶ FIRST_NAME 칼럼에서 'JAMES' 조회하기
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME
FROM EMPLOYEES
WHERE FIRST_NAME = INITCAP('JAMES');
SELECT
LENGTH('HELLO'), LENGTHB('HELLO')
,LENGTH('안녕'), LENGTHB('안녕')
FROM
DUAL;
SELECT
FIRST_NAME || ' ' || LAST_NAME AS FULL_NAME
,CONCAT(CONCAT(FIRST_NAME,' '),LAST_NAME) AS FUU_NAME
FROM
EMPLOYEES;
SELECT
SUBSTR(FIRST_NAME,1,3) -- 1번째 글자부터 3글자를 가져옴
FROM
EMPLOYEES;
SELECT
INSTR(EMAIL,'A') -- 'A'의 위치를 반환
FROM
EMPLOYEES;
SELECT
LPAD(DEPARTMENT_ID,3,0) -- 왼쪽에 0을 채워서 3자리로 조회
,LPAD(NVL(DEPARTMENT_ID,0),3,0)
FROM
EMPLOYEES;
--
SELECT
RPAD(SUBSTR(EMAIL,1,2),5,'*') -- 오른쪽에 *를 채워서 5자리로 조회한다
FROM
EMPLOYEES;
SELECT
LENGTH(LTRIM(' HELLO'))
,LENGTH(RTRIM('HELLO '))
,LENGTH(TRIM(' HELLO '))
FROM
DUAL;
▶ EMPLOYEES 테이블의 사원 정보를 연봉이 높은 순으로 조회하기
연봉순위를 함께 조회하기
SELECT
RANK() OVER(ORDER BY SALARY DESC) AS 연봉순위
,EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,SALARY
FROM EMPLOYEES;
▶ EMPLOYEES 테이블의 사원 정보를 입사순으로 조회하기
먼저 입사한 사원이 1등
SELECT
RANK() OVER(ORDER BY HIRE_DATE) AS 입사순
,EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,HIRE_DATE
FROM EMPLOYEES;
SELECT
DISTINCT DEPARTMENT_ID
,SUM(SALARY) OVER(PARTITION BY DEPARTMENT_ID) AS 부서별연봉합계
,FLOOR (AVG(SALARY) OVER(PARTITION BY DEPARTMENT_ID)) AS 부서별연봉평균
,MAX(SALARY) OVER(PARTITION BY DEPARTMENT_ID) AS 부서별최대연봉
,MIN(SALARY) OVER(PARTITION BY DEPARTMENT_ID) AS 부서별최저연봉
,COUNT* OVER(PARTITION BY DEPARTMENT_ID) AS 부서별사원수
FROM
EMPLOYEES
WHERE
DEPARTMENT_ID IS NOT NULL;
▶ RANK() 함수와 PARTITION BY를 함께 사용하면 그룹 내 순위 구하기 가능
SELECT
RANK() OVER(PARTITION BY DEPARTMENT_ID ORDER BY SALARY DESC) AS 부서내연봉순위
,EMPLOYEE_ID
,FIRST_NAME
,LAST_NAME
,SALARY
,DEPARTMENT_ID
FROM
EMPLOYEES
ORDER BY
DEPARTMENT_ID ASC;
DECODE(표현식
, 값1, 결과1
, 값2, 결과2
, 값3, 결과3
, ...)
▶ JOIN 없이 EMPLOYEES 테이블만 이용하여 EMPLOYEE_ID, DEPARTMENT_NAME 조회하기
SELECT
EMPLOYEE_ID
,DECODE(DEPARTMENT_ID
, 10, 'Administration'
, 20, 'Marketing'
, 30, 'Purchasing'
, 40, 'Human Resources'
, 50, 'Shipping'
, 60, 'IT') AS 부서명
FROM
EMPLOYEES;
▶ EMPLOYEE_ID, PHONE_NUMBER, REGION 조회하기
-- PHONE_NUMBER REGION
-- 011 MOBILE
-- 515 EAST
-- 590 WEST
-- 603 SOUTH
-- 650 NORTH
SELECT
EMPLOYEE_ID
, PHONE_NUMBER
, DECODE(SUBSTR(PHONE_NUMBER,1,3)
,'011','MOBILE'
,'515','EAST'
,'590','WEST'
,'603', 'SOUTH'
,'650','NORTH') AS REGION
FROM
EMPLOYEES;
-- CASE
-- WHEN 조건식1 THEN 결과값1
-- WHEN 조건식2 THEN 결과값2
-- ...
-- ELSE 결과값N
-- END
-- SALARY <10000 : C
-- SALARY <20000 : B
-- SALARY >= 20000 : A
SELECT
EMPLOYEE_ID
,SALARY
,CASE
WHEN SALARY <10000 THEN 'C'
WHEN SALARY <20000 THEN 'B'
ELSE 'A'
END AS 구분
FROM
EMPLOYEES;
▶ 퇴직금정산대상 : 근무개월수가 240개월 이상이면 '정산대상', 아니면 빈 문자열
EMPLOYEE_ID, HIRE_DATE(YYYY-MM-DD), 근무개월수, 퇴직금정산대상유무
SELECT
EMPLOYEE_ID AS 사원번호
,TO_CHAR(HIRE_DATE,'YYYY-MM-DD')AS 입사일
,FLOOR(MONTHS_BETWEEN(SYSDATE, HIRE_DATE)) AS 근무개월수
,CASE
WHEN MONTHS_BETWEEN(SYSDATE, HIRE_DATE) >= 240 THEN '정산대상'
ELSE ''
END AS 퇴직금정산대상유무
FROM
EMPLOYEES;