SQL 함수 종류
■ SQL 함수의 기능
- 기본적인 query문을 더욱 강력하게 해준다.
- 데이터의 계산 수행
- 개별 데이터의 항목 수정
- 표시할 날짜 및 숫자 형식 지정
- 일 데이터 유형 변환
■ SQL 함수 종류
단일 행 함수 : 행 당 하나의 결과 반환
다중 행 함수 : 행 그룹을 조작해 행 그룹당 하나의 결과를 반환
단일 행 함수
데이터 조작(1:1매칭)을 위해 사용
인수를 사용하여 값을 반환
인수:상수,변수,컬럼,표현식
행 당 하나의 결과를 반환
SELECT, WHERE , ORDER BY 절에 사용할 수 있다
데이터 타입을 변경 할 수 있다
중복 사용 가능
종류 - 문자함수 : 문자를 입력하면 문자 또는 숫자를 변환
* LOWER(char) 모든 문자 소문자 변환 / UPPER(char) 모든 문자를 대문자로 변환
* INITCAP(char) 단어 첫문자 대문자 나머지 소문자
* LENGTH(char) 문자의 길이를 표시
* CONCAT(char1,char2) 문자열을 결합 (||)와 같은 기능이지만 두 개의 문자만 결합가능
** SUBSTR(char,m[,n]) 문자열 중 지정한 위치(m)에서 지정한 길이(n)만큼 문자 추출(n생략시 끝까지 추출,m이 음수면 뒤부터 추출
** INSTR(char1,char2[,m][,n]) 문자열 중 지정한 위치(m)에서 특정문자(char2)가 특정 순서(n)로 나타나는 문자열 위치
--문제1)EMP 테이블에서 SCOTT의 사원번호, 성명,담당업무(소문자로),부서번호를 출력 (단,WHERE절에서 LOWER사용)
SELECT EMPNO,ENAME,lower(JOB) as JOB,DEPTNO
FROM EMP
WHERE lower(ename) ='scott';
--문제2)EMP 테이블에서 SCOTT의 사원번호, 성명,담당업무(대문자로),부서번호를 출력 (단,WHERE절에서 UPPER사용)
SELECT EMPNO,ENAME,upper(JOB),DEPTNO
FROM EMP
WHERE UPPER(ename) = 'SCOTT';
--문제3)DEPT 테이블에서 부서이름(DNAME)을 첫 글자만 대문자로 변환하여 출력하여라.
SELECT INITCAP(DNAME)
FROM DEPT;
--문제4)EMP 테이블에서 이름의 첫 글자가 'K'보다 큰 사원의 사원번호, 이름, 업무를 출력하여라.
SELECT EMPNO, ENAME, JOB
FROM EMP
WHERE SUBSTR(ENAME,1,1) > 'K';
--문제5)EMP 테이블에서 이름이 6자리 이상인 사원의 이름과 업무를 출력하여라.
SELECT EMPNO, ENAME, JOB
FROM EMP
WHERE LENGTH(ENAME) >= 6;
--문제6)EMP 테이블에서 이름 중'L'자의 위치를 출력하여라.
SELECT ENAME,instr(ENAME,'L')
FROM EMP;
SELECT ENAME , INSTR(ENAME,'L') AS E_NULL, INSTR(ENAME,'L',1,1) AS E_11
FROM EMP
ORDER BY ENAME;
* LPAD(char1,n[,char2]) : char1 왼쪽에 char2를 끼워 넣어 전체 문자가 n개가 되도록 만든다.
* RAPD(char1,n[,char2]) : char1 오른쪽에 char2를 끼워 넣어 전체 문자가 n개가 되도록 만든다.
--문제1) 이름에 *를 왼쪽에 채워 모두 동일한 15개의 이름으로 변환하고 업무와 급여를 출력한다.
SELECT LPAD(ENAME,15,'*'),JOB,SAL
FROM EMP;
--문제2) 급여를 모두 동일하게 만단위로 보여지게 변환하고 이름과 부서번호를 함께 출력한다.
SELECT LPAD(SAL,5,'0'),ENAME,DEPTNO
FROM EMP;
* LTRIM(char1[,char2]) : char1의 왼쪽에서 char2를 제거 한다. (char2 생략 시 공백 제거)
* RTRIM(char1[,char2]) : char1의 오른쪽에서 char2를 제거 한다. (char2 생략 시 공백 제거)
* TRIM : char1에서 앞뒤로 특정문자를 제거 한다.( 제거문자 생략시 공백 제거,return 타입은 varchar2)
TRIM(
[LEADING | TRAILING | BOTH]
[제거문자]
[FROM]
제거대상
)
* TRANSLATE(char,str1,str2) : char에 있는 str1 표현을 str2로 각각 모두 변환한다.
* REPLACE(char1,str1,str2) : 문자열 그대로를 변환
--문제1) EMP 테이블에서 성명을 소문자로 바꾸어 출력하여라. (단, TRANSLATE 함수를 사용 하여라)
SELECT TRANSLATE(ENAME,'ABCDEFGHIJKLMNOPQRSTUWXYZ','abcdefghijklmnopqrstuwxyz') AS RESULT
FROM EMP;
SELECT TRANSLATE(ENAME,UPPER(ENAME),LOWER(ENAME)) AS RESULT
FROM EMP;
--문제2) EMP 테이블에서 JOB에 'A'를 '$'로 바꾸어 출력하여라.
SELECT DISTINCT TRANSLATE(JOB,'A','$')
FROM EMP;
SELECT DISTINCT REPLACE(JOB,'A','$')
FROM EMP;
■ 숫자함수 : 숫자를 입력하면 숫자 값을 변환 n m
* ROUND(n[.m]) : n값을 m자리에서 반올림 (1234.5678) = (-4,-3,-2,-1,0,1,2,3)
m > 0 이면 소수점 아래 m-1 자리에서 반올림
생략 시 정수 이하 반올림(소수점 첫 자리 반올림)
m < 0 이면 m번째 자리에서 반올림
* TRUNC(n[,m]) : n 값을 m자리에서 버림
* MOD(n,m) : n값을 m값으로 나눠 나온 나머지
* ABS(n) : n의 절대값을 계산하여 반환
* FLOOR(n) : FLOOR함수는 주어진 값보다 작지만 같은 최대 정수를 구하는 함수
* CEIL(n) : 주어진 값보다는 크지만 가장 근접하는 최소값을 구하는 함수
* SIGN(n) : 숫자가 양수이면 1, 음수이면 -1, 0이면 0을 반환
날짜함수 : 날짜 유형을 변환
* MONTHS_BETWEEN(d1,d2) : d1,d2 두 날짜 간의 개월 수 차이 값 반환
* ADD_MONTHS(d1,n) : d1날짜에 n개월 더한 값 반환
* NEXT_DAY(d1,n) : d1 다음의 지정한 요일에 해당하는 날짜 반환 (일요일1,월요일2,..토요일7)
* LAST_DAY(d1) : 해당 월의 마지막 날짜 반환
* ROUND(d1,char) : 날짜를 년, 월 단위로 반올림
* TRUNC(d1,char) : 날짜를 년,월 단위로 버림 (char = "month" , "year")
* EXTRACT(day | month | year from d1) : 특정 날짜에서 일,월,년을 각각 뽑아내는 함수 select hiredate,
extract(day from hiredate) as days,
extract(month from hiredate) as months,
extract(year from hiredate) as years
from emp;
-- 문제4) EMP 테이블에서 입사한 달의 근무 일수를 계산하여 출력하여라. 단, 토요일과 일요일도 근무 일수에 포함한다.
SELECT ENAME AS "사원명" ,HIREDATE AS "입사날짜",
EXTRACT(DAY FROM LAST_DAY(HIREDATE))-EXTRACT(DAY FROM HIREDATE) AS "입사 달 근무일수"
FROM EMP;
-- 문제5) EMP 테이블에서 10번 부서원의 입사 일자로부터 돌아오는 금요일을 계산하여 출력하여라.
SELECT ENAME AS "사원명", HIREDATE AS "입사날짜",
NEXT_DAY(HIREDATE,6) AS "돌아오는 금요일"
FROM EMP
WHERE DEPTNO = 10;
--문제6 ) 봉급과 커미션(COMM) 합계가 봉급의 10% 인상된 급여보다 많은 사원의 이름,급여 및 커미션을 표시하도록 한다.
SELECT ENAME, SAL, COMM
FROM EMP
WHERE COMM+SAL > SAL*1.1
AND COMM IS NOT NULL;
--문제7 ) 커미션을 받지 않는 사원의 급여를 10% 인상하여 표시하되, 다음의 형식으로 출력하여라
-- :The salary of SMITH after a 10% raise is 2000
SELECT ENAME 사원명,sal 원래봉급, 'The salary of ' ||ENAME||' after a 10% raise is '||(sal+sal*0.1) AS "COMMENT"
FROM EMP
WHERE COMM IS NOT NULL;
-- 문제8 ) EMP 테이블에서 현재까지 근무일수가 몇 주, 몇 일인가를 출력하여라.
-- 단, 근무일수가 많은 사람 순으로 출력하여라. TO_NUMBER(CHAR) 문자를 숫자로 바꿔줌`
select ename as "사원명",
hiredate as "입사날짜",
trunc((sysdate-hiredate)) as "근무일수" ,
trunc(trunc((sysdate-hiredate))/7) as "근무 주"
from emp
order by hiredate asc;
-- 문제9) EMP 테이블에서 부서번호 10번의 현재까지의 근무 월수를 계산하여 출력하여라.
SELECT ENAME AS "사원",ROUND(MONTHS_BETWEEN(SYSDATE,HIREDATE)) AS "근무 월수"
FROM EMP
WHERE DEPTNO=10;
[이외문제 풀어보세요]
--문제1)EMP 테이블에서 scott의 사원번호, 성명,담당업무(소문자로),부서번호를 출력 (단,WHERE절에서 LOWER사용)
--문제2)EMP 테이블에서 scott의 사원번호, 성명,담당업무(대문자로),부서번호를 출력 (단,WHERE절에서 UPPER사용)
--문제3)DEPT 테이블에서 부서이름(DNAME)을 첫 글자만 대문자로 변환하여 출력하여라.
--문제4)EMP 테이블에서 이름의 첫 글자가 'K'보다 큰 사원의 사원번호, 이름, 업무를 출력하여라.
--문제5)EMP 테이블에서 이름이 6자리 이상인 사원의 이름과 업무를 출력하여라.
--문제6)EMP 테이블에서 이름 중'L'자의 위치를 출력하여라.
--문제7) 이름에 *를 왼쪽에 채워 모두 동일한 15개의 이름으로 변환하고 업무와 급여를 출력한다.
--문제8) 급여를 모두 동일하게 만단위로 보여지게 변환하고 이름과 부서번호를 함께 출력한다.
--문제9) EMP 테이블에서 성명을 소문자로 바꾸어 출력하여라. (단, TRANSLATE 함수를 사용 하여라)
--문제10) EMP 테이블에서 JOB에 'A'를 '$'로 바꾸어 출력하여라.
--문제11) 봉급과 커미션(COMM) 합계가 봉급의 10% 인상된 급여보다 많은 사원의 이름,급여 및 커미션을 표시하도록 한다.
--문제12) 커미션을 받지 않는 사원의 급여를 10% 인상하여 표시하되, 다음의 형식으로 출력하여라
-- :The salary of SMITH after a 10% raise is 2000
-- 문제 13) EMP 테이블에서 현재까지 근무일수가 몇 주, 몇 일인가를 출력하여라.
-- 단, 근무일수가 많은 사람 순으로 출력하여라. TO_NUMBER(CHAR) 문자를 숫자로 바꿔줌
-- 문제 14) EMP 테이블에서 10번 부서원의 현재까지의 근무 월수를 계산하여 출력하여라.
-- 문제 15) EMP 테이블에서 입사한 달의 근무 일수를 계산하여 출력하여라. 단, 토요일과 일요일도 근무 일수에 포함한다.
-- 문제 16) EMP 테이블에서 10번 부서원의 입사 일자로부터 돌아오는 금요일을 계산하여 출력하여라.
변환함수 : 데이터 유형 변환
* TO_CHAR : 숫자, 날짜 타입의 DATA를 VARCHAR2타입의 문자형식으로 변환
형식:TO_CHAR(char1,'type')
type에 문자나 특수문자를 넣고 싶을 경우 따옴표 사용
type의 경우 입력된 대소문자대로 출력
select to_char('34000','00000') from dual;
* TO_NUMBER : 문자 String을 number 타입으로 변환
select '1234', to_number('1234','9999') from dual;
* TO_DATE : 문자 String을 날짜 타입으로 변환
select to_date('20150925','YYYY-MM-DD') from dual;
@ 숫자코드
9: 일반적인 숫자형식을 나타내며, 자리 수를 다 채우진 않음
0: 자리 수가 비면 0으로 채워준다
$: $표시
S: 양수이면 + , 음수이면 -
@ 날짜코드
MM : 월수, MON : 월 이름을 3자리 문자로 표현 ex)JAN,FEB,MAR 등, MONTH : 월 이름( ex: JANUARY,FEBLARY,MARCH 등)
DD : 날짜, D : 그 주의 몇 번째 날짜인지(일요일:0,,,토요일:7), DY: 요일 이름을 3자리 문자로 표현(SUN,MON,TUE)
DAY : 요일이름
YYYY : 년도, YY : 년도 마지막 2자리 HH : HH12처럼 12시간제 HH12 : 12시간제 HH24 : 24시간제
MI : 분, SS : 초, SSSS : 초 두 번 출력, W : 그 날의 주 수, WW : 그 해의 주 수, Q : 분기
Language 변경 옵션-common-enviroment (american_america.ko16mswin949)
regedit 편집
-- HKEY_LOCALMACHINEWSUFTWAREWORACLE의 NLS_LANG 변경
■ 기타함수
* COALESCE(exp|,....expn) : exp1,....expn 중 null이 아닌 첫 번째 값 출력
모든 데이터타입에 적용 가능
전환되는 값의 데이터 타입을 일치시켜야 한다
case문으로 변경가능
select sal, comm, coalesce(comm,0)
from emp;
select sal, comm,
case
when (comm is not null) then comm*1.1
else 0+10
end
from emp;
-- 문제1) EMP 테이블에서 이름, 보너스, 연봉, 보너스가 null이 아닌 경우 보너스를, 보너스가 null인 경우에는 연봉을
-- 모두 null이면 50으로 표시한다.
select sal, comm, coalesce(comm,sal,50)
from emp;
select sal, comm,
case
when (comm is not null) then comm
when (sal is not null) then sal
else 50
end as result
from emp;
* DECODE : if-then-else 문의 역할 수행
데이터들을 다른 값으로 바꿔준다
형식 : decode(value,if1,then1,if2,then2,...else1)
value값이 if1일 경우에 then1값으로 바꾸어 주고, value 값이 if2일 경우엔 then2값 나머지는 else로 바꿔줌
select sal, comm, coalesce(comm,0) // 두개의 인자 형태가 같아야함
from emp;
select sal, comm, decode(comm,null,' ',comm) as result // 문자로 표현하고 싶을 때 디코더 사용
from emp;
--문제1) EMP 테이블에서 부서번호가 10이면 'A'로, 20이면 'B'로, 30이면 'C'로 바꾼 뒤
-- 이름, 업무, 부서번호와 함께 출력
SELECT ENAME,JOB,DEPTNO,
DECODE(DEPTNO,10,'A',20,'B','C')
FROM EMP;
--문제2) EMP 테이블에서 JOB이 ANALYST이면 급여증가는 10%이고, CLERK이면 15%, MANAGER이면 20%이고,
-- 다른 업무에 대해서는 급여 증가가 없다. 사원번호,이름,업무,급여,증가된 급여를 출력
SELECT EMPNO,ENAME,JOB,SAL,
DECODE(JOB,'ANALYST',SAL*1.1,'CLERK',SAL*1.15,SAL*1.2)
FROM EMP;
*NVL(col,exp1) : col이 null일 경우 exp1로 변환한다
select sal, comm, nvl(comm,0) as result
from emp;
*NVL2(col,exp1,exp2) : col 이 null이면 exp2를 null이 아니면 exp1을 리턴한다.
col 과 exp1 이 달라도 됨
select sal,comm, nvl2(comm,comm,100) as result
from EMP
order by comm nulls first;
*NULLIF(exp1,exp2) : exp1과 exp2값을 비교해 같으면 null 값을, 다르면 exp1 값을 리턴한다
select ename, job, deptno, nullif(deptno,10) as result
from EMP
order by deptno;
--문제1) EMP 테이블의 사원이름, 매니저번호(MGR)를 출력하고, 매니저번호가 NULL이면 '상위관리자'로 표시하고
-- 매니저번호가 있으면 '매니저번호담당'으로 표시하여라
SELECT ENAME,MGR,NVL2(MGR,MGR||'담당','상위관리자')
FROM EMP;
--문제2) EMP 테이블의 사원이름, 업무를 출력하고, 업무가 'CLERK'인 경우 NULL로 나오도록 한다
SELECT ENAME, JOB, NULLIF(JOB,'CLERK')
FROM EMP;
--문제1) decode 함수를 이용하여 급여가 1000보다 작으면 'A', 1000이상 2500이하 이면 'B', 2500이상이면 'C'로 표시하라
select sal ,sign(sal-1000), sign(sal-2500),
decode(sign(sal-1000),-1,'A',sign(sal-2500),'C','B')
from EMP;
--문제2) 문제 1을 case함수를 이용하여 변경하여라
SELECT SAL,
CASE
WHEN(SAL<1000) THEN 'A'
WHEN(SAL>=1000 AND SAL<=2500) THEN 'B'
ELSE 'C'
END
FROM EMP;
test_data --> 29개 테이블
student, professor, DEPARTMENT , emp2 , dept2 주로 쓸 것임.
*테이블 생성 혹은 입력시 에러 나는 경우(한글깨짐)
nls_lang 설정
1. regedit 설정
2. orange 환경변수 설정
american_america.ko16mswin949
-- ** 연습 문제 1 **
--Student 테이블을 사용하는 학생들의 이름과 주민번호, 성별을 출력하되 성별은 주민번호(Jumin)컬럼을 이용하여
--7번째 숫자가 1일 경우 "남자", 2일 경우 "여자"로 출력하세요
SELECT NAME AS "이름",JUMIN AS "주민번호", DECODE(SUBSTR(JUMIN,7,1),1,'남자',2,'여자') AS "성별"
FROM STUDENT;
-- ** 연습 문제 2 **
--Student 테이블에서 학생의 이름과 전화번호와 지역명을 출력하세요. 지역번호가 02는 서울, 031은 경기,
--051은 부산, 052는 울산, 053은 대구, 055,는 경남으로 출력하세요
SELECT NAME AS "학생이름" , TEL AS "전화번호",
DECODE(SUBSTR(TEL,1,INSTR(TEL,')')-1),
'02','서울','031','경기','051','부산','052','울산','053','대구','055','경남') AS "지역번호"
FROM STUDENT;
-- ** 연습 문제 3 **
--Student 테이블의 Jumin 컬럼을 참조하여 학생들의 이름과 태어난 달, 그리고 분기를 출력하세요.
--태어난 달이 01-03월 은 1/4분기, 04-06월 은 2/4분기, 07-09월은 3/4분기 10-12월은 4/4분기로 출력하세요
SELECT NAME AS "학생이름", TRIM(LEADING '0' FROM SUBSTR(JUMIN,3,2)) ||'월' AS "출생 월",
DECODE(-1,SIGN(9-SUBSTR(JUMIN,3,2)),'4분기',SIGN(6-SUBSTR(JUMIN,3,2)),'3분기',
SIGN(3-SUBSTR(JUMIN,3,2)),'2분기',SIGN(0-SUBSTR(JUMIN,3,2)),'1분기')
FROM STUDENT;
SELECT DECODE(TO_CHAR(TO_DATE(SUBSTR(JUMIN,3,2),'MM'),'Q'), 1,'1/4 분기', 2,'2/4 분기',3,'3/4 분기',4,'4/4 분기') FROM STUDENT;
-- ** CASE 연습 문제 **
-- 교수테이블 (PROFESSOR) 를 조회하여 교수의 급여액수(보너스포함)를 기준으로 200 미만은 4급
-- 201-300 까지는 3급, 301 - 400 까지는 2급, 401 이상은 1급으로 표시하여 교수의 번호,이름,급여,등급을 출력하시오
-- (단 BONUS가 NULL인 경우는 0으로 처리)
SELECT NAME AS "교수명", PROFNO AS "교수번호",PAY+NVL(BONUS,0) AS "급여",
CASE
WHEN(PAY+NVL(BONUS,0) < 200) THEN '4급'
WHEN(PAY+NVL(BONUS,0) >= 201 AND PAY+NVL(BONUS,0)<=300) THEN '3급'
WHEN(PAY+NVL(BONUS,0) >= 301 AND PAY+NVL(BONUS,0)<=400) THEN '2급'
ELSE '1급'
END AS "등급"
FROM PROFESSOR;
■ 그룹 함수
* COUNT : 조건을 만족하는 모든 행의 수 ( 모든 데이터 타입 가능 ) ( NULL 값은 안읽음 ) (*) 시 가능
* SUM : 조건을 만족하는 모든 행의 합계
* AVG : 조건을 만족하는 모든 행의 평균
* MAX : 조건을 만족하는 모든 행의 최댓값 ( 모든 데이터 타입 가능 )
* MIN : 조건을 만족하는 모든 행의 최솟값 ( 모든 타입 가능 )
* STDDEV : 조건을 만족하는
그룹 함수 구문
SELECT 그룹함수([DISTINCT]{ COLLUMN,.,,} -5
FROM 테이블 명 -1
[WHERE 조건] -2
[GROUBP BY COLUMN1,COLUMN2...] -3
[HAVING 그룹조건] -4
[ORDER BY COLUMN1,COLUMN2....,,] -6
* GROUP BY 절을 사용하여 테이블의 행을 더 작은 그룹으로 나 눈다.
* SELECT 목록의 열 중 그룹 함수에 없는 열은 모두 GROUP BY절에 포함 되어야한다.
* GROUP BY 열을 SELECT 절에 포함시키지 않아도 된다.
* 하나 이상의 GROUP BY 열을 나열하여 그룹에 대한 요약 결과를 조회할 수 있다.
--문제1) EMP 테이블에서 각 부서별로 사원수, 최대연봉, 최소연봉, 평균연봉을 구하고 급여평균으로 정렬 하여라.
SELECT DEPTNO,COUNT(*) AS "사원수" ,MAX(SAL) AS "최대연봉",MIN(SAL) AS "최소연봉", TRUNC(AVG(SAL)) AS "평균연봉"
FROM EMP
GROUP BY DEPTNO
ORDER BY 평균연봉;
--문제2) EMP 테이블에서 각 업무별로 사원수, 급여평균을 구하고 업무별로 정렬 하여라.
SELECT JOB, COUNT(JOB) AS "사원수",TRUNC(AVG(SAL)) AS "급여평균"
FROM EMP
GROUP BY JOB;
ORDER BY JOB;
--문제3) EMP 테이블에서 업무별,부서별로 그룹하여 각각의 인원수와 급여평균을 구하고 급여평균이 많은 순으로 정렬 하여라.
SELECT JOB,DEPTNO,COUNT(*),AVG(SAL)
FROM EMP
GROUP BY JOB,DEPTNO
ORDER BY AVG(SAL) DESC;
■ HAVING 절
WHERE 사용하여 그룹을 제한할 수 없다
HAVING 절을 사용하여 그룹을 제한한다
그룹이 형성되고 그룹함수가 계산된 후 HAVING절이 적용된다
HAVING 절이 GROUP BY 절 앞에 올 수는 있지만 뒤에 쓸 것을 권장한다
SELECT절 보다 먼저 수행되므로 ALIAS를 사용할 수 없다
--문제1)EMP 테이블에서 부서 인원이 4명보다 많은 부서의 부서번호, 인원수, 급여의 합을 출력하여라
SELECT DEPTNO AS "부서번호“,COUNT(*) AS "인원수”,SUM(SAL) AS “급여의 합”
FROM EMP
GROUP BY DEPTNO
HAVING COUNT(*) > 4;
--문제2)EMP 테이블에서 업무별 급여의 평균이 3000이상인 업무에 대해서 업무명, 평균 급여, 급여의 합을 구하여라
SELECT JOB,ROUND(AVG(SAL)),SUM(SAL)
FROM EMP
GROUP BY JOB
HAVING AVG(SAL)>=3000;
'Study Note > Database' 카테고리의 다른 글
JOIN (0) | 2016.02.04 |
---|---|
집합 연산자 (0) | 2016.02.04 |
SQL 기본 [ SELECT ] (0) | 2016.02.03 |
DataPump (0) | 2016.02.02 |
Flashback (0) | 2016.02.02 |