2019. 12. 10. 09:18ㆍSecurity/sql
* 변환함수
년도 : YYYY로 표기. 두 자리로는 표기하지 않는다.
월 : MONTH, NON도 있지만 공문서에는 MM으로 표기한다(ex : 03, 04)
일 : DD가 기본 형식(ex 01, 02)이며 필요할 경우 DAY(영문 또는 한글 요일)와 DY(약자로 표현된 요일)를 같이 써준다.
시 : HH24(24시 형식)이 기본이지만 HH(12시 형식)을 사용할 경우 AM/PM을 같이 사용한다.
분 : MI
초 : SS(두 자리 초 표시). SSSSSS 하루를 초로 환산한 표현 방식(0~86399)
TO_CHAR : 날짜나 숫자를 문자로 변환. 내가 원하는 형태로 출력하고 싶을때 사용
ex) TO_CHAR(날짜, 출력형식), TO_CHAR(숫자, 출력형식)
TO_DATE : 데이터를 날짜형으로 해석. ex) TO_DATE(문자, 해석형식)
[예제 1]현재 날짜를 다양한 형식으로 출력.
SELECT TO_CHAR(sysdate, 'YYYY/MM/DD') 날짜,
TO_CHAR(sysdate, 'YYYY/MM/DD:HH24:MI:SS') 날짜, // 두번째가 표준서식
TO_CHAR(sysdate, 'YYYY/MM/DD:HH:MI:SS AM') 날짜
FROM dual;
SELECT TO_CHAR(sysdate, '"오늘은 "YYYY"년 "MM"월 "DD"일 입니다."') 날짜
FROM DUAL;
[예제 2]10번 부서 사원의 입사일을 'XXX 사원의 입사일은 XXXX년 XX월 XX일입니다.'의 형식으로 출력
SELECT ename||' 사원의 입사일은 '|| TO_CHAR(hdate, 'YYYY"년 "MM"월 "DD"일 입니다."') 입사일
FROM emp
WHERE dno = '10';
[예제 3]다양한 형식으로 숫자를 출력
SELECT TO_CHAR(12345.678, '999,999.99999') num FROM dual; // 소수점 이하는 지정한 자리에 0을 채우고 앞은 무시
[3-1]
SELECT TO_CHAR(12345.678, '099,999.999') num FROM dual;
[3-2]
SELECT TO_CHAR(12345.678, '9,9999.9') num FROM dual; // 소수점 이하가 부족하면 반올림
[3-3]
SELECT TO_CHAR(12345.678, '9,999.9') num FROM dual; / /소수점 앞부분이 부족하면 출력장애
[3-4]
SELECT TO_CHAR(1234, '$999,999') num FROM dual;
[3-5]
SELECT TO_CHAR(1234, 'L999,999') num FROM dual; // 원화를 지원하지 않을 경우 엔화나 위안이 출력.
[3-6]
SELECT TO_CHAR(123456789, '9.999EEEE') num FROM dual;
[예제 4]10번 부서 사원의 보너스가 급여의 몇 퍼센트인지 검색
SELECT eno 사번, ename 이름,
TO_CHAR(NVL(comm, 0)/(sal*12)*100, '90.99')||'%' 급여_비율 // 90.99에 0을 지정해야 0.96이 .96으로 나오는 것을 방지
FROM emp
WHERE dno='10';
[예제 5]1992년 이전에 입사한 사원의 정보를 검색
SELECT eno 사번, ename 이름, hdate 입사일
FROM emp
WHERE hdate < TO_DATE('19920101', 'YYYYMMDD');
[실습]
1. 학생의 평균 평점을 'XXX 학생의 평균 평점은 x.xx입니다.' 형식으로 소수점 이하 두 자리까지 검색
SELECT sname||' 학생의 평균 평점은 '|| TO_CHAR(avr, '0.99')||'입니다.' 평균_평점
FROM student;
2. 교수의 부임일을 'XXX교수의 부임일은 YYYY년 MM월 DD일입니다.' 형식으로 검색
SELECT pname||' 교수의 부임일은 '|| TO_CHAR(hiredate, 'YYYY"년 "MM"월 "DD"일 입니다."') 부임일
FROM professor;
3. 교수 중에 3월에 부임한 교수의 명단을 검색
SELECT pno 교번, pname 이름, hiredate 부임일
FROM professor
WHERE TO_CHAR(hiredate, 'MM') = 03;
4. 화학과 1학년 학생들의 4.5 환산 평점을 'XXX 학생의 4.5 환산 평점은 x.xx입니다.' 형식으로 소수점 이하 두 자리까지 검색.
SELECT sname||' 학생의 4.5 환산 평점은 '|| TO_CHAR(avr*4.5/4, '0.99')||'입니다.' "4.5 환산_평점"
FROM student
WHERE syear = '1' AND major = '화학';
* 그룹 함수
MAX : 최대 값을 반환. MAX(컬럼)
MIN : 값들 중에 최소 값을 반환. MIN(컬럼)
AVG : 평균 값을 계산 AVG(컬럼)
COUNT : 반환된 행의 수를 계산. COUNT(컬럼 | *)
SUM : 합계를 계산. SUM(컬럼)
STDDEV : 표준편차를 계산. STDDEV(컬럼)
VARIANCE : 분산을 계산. VARIANCE(컬럼)
그룹 함수를 사용하는 경우 고려 사항
- NULL값은 무시.
- 반드시 단하나의 값만을 반환.
- GROUP BY 설정 없이 일반 컬럼과 기술될 수 없다.
[예제 1]사원의 급여 평균을 검색
SELECT AVG(sal) 평균급여, ROUND(AVG(sal)) 평균급여 // ROUND외에 to_char도 사용 가능
FROM emp;
[예제 2] 사원들에게 지급된 보너스 총합과 보너스 평균을 검색.
SELECT SUM(comm) 총액,
ROUND(AVG(comm)) 평균, COUNT(comm) 수령인원, // 보너스를 받는 사람으로만 평균 계산
ROUND(AVG(NVL(comm,0))) 환산평균, COUNT(*) 전체인원 // 보너스를 받지 않는 사람까지 포함해서 평균 계산
FROM emp;
SELECT COUNT(*)
FROM emp
WHERE comm IS NOT NULL; // null이 아닌 사원만 검색
숫자컬럼에 NULL이 들어가면 안되는 이유를 보여준 문제. 계산오류가 날 가능성이 엄청 높다.
[예제 3] 10번 부서원들보다 급여가 높은 사원을 검색.
SELECT eno 사번, ename 이름, dno 부서번호
FROM emp
WHERE sal > (SELECT MAX(sal)
FROM emp
WHERE dno = '10');
* 그룹 함수와 GROUP BY절
형식
SELECT [DISTINCT/ALL] 컬럼 or 그룹함수, ...
FROM 테이블
WHERE 조건
GROUP BY Group대상 -> GROUP의 위치.
ORDER BY 정렬대상 [ASC/DESC]
그룹함수 사용할때만 GROUP BY절 사용
[예제 4]업무별 평균 급여, 평균 연봉과 부서별 평균 연봉을 검색.
SELECT job 업무, ROUND(AVG(sal)) 평균_급여,
ROUND(AVG(sal*12+NVL(comm,0))) 평균_연봉
FROM emp
GROUP BY job;
GROUP BY가 없으면 기수가 다르기때문에 출력이 안됨. 일반 컬럼에 있으면 반드시 GROUP BY절에 반드시 있어야 한다.
SELECT d.dno 부서번호, dname 부서명, ROUND(AVG(sal*12+NVL(comm,0))) 평균_연봉
FROM dept d, emp e
WHERE d.dno = e.dno
GROUP BY d.dno, dname
ORDER BY d.dno;
[예제 5] 부서별로 급여 평균의 최대 값과 최소 값을 검색.
SELECT dno 부서번호,
MAX(AVG(sal)) 최대평균, MIN(AVG(sal)) 최소평균 // dno는 여러개지만 나머지는 1개라서 출력 불가
FROM emp
GROUP BY dno;
[예제 7] 각 부서별 최소 급여를 받는 사원의 정보를 검색.
SELECT d.dno, dname, eno, ename, sal
FROM emp e, dept d
WHERE d.dno=e.dno
AND (d.dno, sal) IN (SELECT dno, MIN(sal)
FROM emp
GROUP BY dno)
ORDER BY d.dno;
[실습]
1. 각 학과별 학생 수를 검색한다.
SELECT major 전공, COUNT(sno)
FROM student
GROUP BY major;
2. 화학과와 생물학과 학생 4.5 환산 평점의 평균을 각각 검색.
SELECT sno 학번, sname 이름, major 학과, TO_CHAR(AVG(avr*4.5/4), '0.99') "4.5 환산 평점"
FROM student
WHERE major IN ('화학', '생물')
GROUP BY sno, sname, major;
3. 부임일이 10년 이상 된 직급별(정교수, 조교수, 부교수) 교수의 수를 검색.
SELECT orders 직위, COUNT(pno)
FROM professor
WHERE 120 <= MONTHS_BETWEEN(sysdate, hiredate)
GROUP BY orders;
4. 과목명에 화학이 포함된 과목의 학점수 총합을 검색.
SELECT SUM(st_num) 이름에_화학이_포함된_과목
FROM course
WHERE cname like '%화학%';
5. 화학과 학생들의 기말고사 성적을 성적순으로 검색.
SELECT s.sno 학번, s.sname 이름, s.major 전공, TO_CHAR(AVG(sc.result), '00.99') 기말고사_성적
FROM student s, score sc
WHERE s.sno = sc.sno
AND major = '화학'
GROUP BY s.sno, s.sname, s.major
ORDER BY AVG(sc.result) desc;
6. 학과별 기말고사 평균을 성적순으로 검색한다.
SELECT s.major 학과, TO_CHAR(AVG(sc.result), '00.99') 기말고사_성적
FROM student s, score sc
WHERE s.sno = sc.sno
GROUP BY s.major
ORDER BY AVG(sc.result) desc;
7. 30번 부서의 업무별 연봉의 평균을 검색.(단, 출력 양식은 소수 이하 두 자리까지 통일된 형식으로 출력)
SELECT d.dno 부서번호, e.job 업무,TO_CHAR(AVG(sal*12+NVL(comm,0)), 'L99999.99') 평균_연봉
FROM dept d, emp e
WHERE d.dno = e.dno
AND d.dno = '30'
GROUP BY d.dno, e.job
ORDER BY AVG(sal*12+NVL(comm,0)) desc;
8. 물리학과 학생 중에 학년별로 성적이 가장 우수한 학생의 평점을 검색.
SELECT s.sno 학번, s.sname 이름, major 전공, syear 학년, TO_CHAR(MAX(avr), '0.99') 성적
FROM student s
WHERE s.major = '물리'
AND (s.syear, avr) IN (SELECT syear, MAX(AVR)
FROM student
WHERE major='물리'
GROUP BY syear)
GROUP BY s.sno, s.sname, s.major, s.syear
ORDER BY syear desc;
9. 학년별로 환산 평점의 평균값을 검색한다. 단 출력 양식은 소수이하 두 자리까지 통일된 양식으로 출력.
SELECT syear 학년별, TO_CHAR(AVG(avr*4.5/4), '0.00') 평점
FROM student
GROUP BY syear;
10. 화학과 1학년 학생 중 평점이 평균 이하인 학생을 검색한다.
SELECT sno 학번, sname 이름, major 전공, syear 학년, avr 평점
FROM student
WHERE avr <= (SELECT AVG(avr)
FROM student
WHERE major = '화학' AND syear = 1)
AND major = '화학' AND syear = 1;
* 그룹 함수와 HAVING절
형식
SELECT [DISTINCT/ALL] 컬럼 or 그룹함수, ...
FROM 테이블
WHERE 조건
GROUP BY Group대상
HAVING <그룹 함수 포함 조건>
ORDER BY 정렬대상 [ASC/DESC];
[예제 1] 부서별 급여 평균이 3천 달러 미만인 부서의 부서번호와 평균 급여를 검색.
SELECT dno 부서번호, ROUND(AVG(sal)) 평균급여
FROM emp
GROUP BY dno
HAVING AVG(sal) < 3000;
[예제 2] HAVING절의 다양한 사용법
SELECT dno 부서번호, COUNT(*) 인원수
FROM emp
GROUP BY dno
HAVING job != '개발'; // 그룹 함수가 들어가지 않기 때문에 오류. WHERE절에 써야함.
[예제 3]부서 중 가장 급여를 많이 받는 부서를 검색.
SELECT dno, AVG(sal)
FROM emp
GROUP BY dno
HAVING AVG(sal) = (SELECT MAX(AVG(sal))
FROM emp
GROUP BY dno);
[실습]
1. 화학과를 제외하고 학과별로 학생들의 평점 평균을 검색한다.
SELECT major 전공, TO_CHAR(AVG(avr),'0.90') 평균평점
FROM student
WHERE major != '화학'
GROUP BY major;
2. 화학과를 제외한 각 학과별 평균 평점 중에 평점이 2.0 이상인 정보를 검색한다.
SELECT major, TO_CHAR(AVG(avr),'0.90')
FROM student
WHERE major != '화학'
GROUP BY major
HAVING avg(avr) > 2.0;
3. 기말고사 평균이 60점 이상인 학생의 정보를 검색한다.(학번과 기말고사 평균)
SELECT sno, ROUND(AVG(result))
FROM score
GROUP BY sno
HAVING avg(result) >= 60;
4. 강의 학점수가 3학점 이상인 교수의 정보를 검색한다.(교수번호, 이름과 담당 학점수)
SELECT p.pno, pname, sum(st_num)
FROM professor p, course c
WHERE p.pno = c.pno
GROUP BY p.pno, pname
HAVING sum(st_num) >= 3;
5. 기말고사 성적이 핵 화학과목보다 우수한 과목의 과목명과 담당 교수명 검색한다.
SELECT c.cno, cname, p.pno, pname
FROM course c, professor p
WHERE c.pno=p.pno
AND cno IN (SELECT cno
FROM score
HAVING AVG(result) > (SELECT AVG(result)
FROM score r, course c
WHERE r.cno = c.cno
AND cname='핵화학')
GROUP BY cno);
6. 근무 중인 직원이 4명 이상인 부서를 검색한다.
SELECT dept.dno, dname, COUNT(*)
FROM emp, dept
WHERE dept.dno = emp.dno
GROUP BY dept.dno, dname
HAVING COUNT(*) > 4;
7. 업무별 평균 년봉이 2만불 이상인 업무를 검색한다.
SELECT job, ROUND(AVG(sal*12+NVL(comm,0)))
FROM emp
GROUP BY job
HAVING AVG(sal*12+NVL(comm,0)) >= 20000;
8. 각 학과의 학년별 인원중 인원이 5명 이상인 학년을 검색한다.
SELECT major, syear, COUNT(*)
FROM student
GROUP BY major, syear
HAVING COUNT(*) >= 5;
9. 인원수가 가장 많은 학과를 검색한다.
SELECT major
FROM student
GROUP BY major
HAVING COUNT(*) = (SELECT MAX(COUNT(*))
FROM student
GROUP BY major);
10. 학생 중 기말고사 성적이 가장 낮은 학생의 정보를 검색한다.
SELECT s.sno, sname, ROUND(AVG(result))
FROM student s, score r
WHERE s.sno=r.sno
GROUP BY s.sno, sname
HAVING AVG(result) = (SELECT MIN(AVG(result))
FROM score
GROUP BY sno);
'Security > sql' 카테고리의 다른 글
SQL-테이블 생성과 데이터 타입의 이해 (0) | 2019.12.12 |
---|---|
SQL-DML문의 이해, 트랜잭션과 잠금(lock) (0) | 2019.12.11 |
SQL-집합연산자, 문자, 숫자, 날짜함수 (0) | 2019.12.09 |
SQL-서브쿼리 (0) | 2019.12.06 |
SQL-모델링, join (0) | 2019.12.05 |