2015년 1월 16일 금요일

SQL_정리3

SQL 사용법에 대해 알아 보자


4. WHERE 절을 이용한 조건 검색
 - 이제까지 SELECT 문은 테이블 내의 모든 행을 검색하는 것이었으나 대부분의 테이블들이 수 천 개에서 심지어는 수 억 개에 이르는 엄청난 량의 행을 포함하기 때문에 현실에서 테이블의 모든 행을 검색하는 것은 거의 없다고 봐도 무방함 보통의 업무에서 사용되는 SELECT 문은 테이블의 모든 행을 검색하는 것이 아니라 검색 조건을 이용 원하는 행 만을 검색하는 것이 일반적. 실제로 검색 조건이 없는 쿼리문을 만나는 것은 매우 드믐. 행의 조건을 기술함으로써 테이블 내에 원하는 결과만을 검색하는 WHERE 절을 배워 볼 것임

> 조건 검색
SQL> SELECT [DISTINCT | ALL] 컬럼, 컬럼...
  2     FROM 테이블
  3     WHERE 조건
  4     ORDER BY 컬럼 [ASC/DESC], 컬럼 [ASC/DESC]...
* 조건을 통해 컬럼 내에 데이터를 제한
* WHERE 절은 FROM 절 바로 뒤에 기술
* 조건의 대상은 컬럼, 연산자, 수식 등이 가능
* 조건에 이용되는 비교 연산자
 =, <, >, <=, >=, (!=, <>, ^= : 같지 않음을 뜻함)

-예제1. 다음 각 조건에 맞는 정보를 검색
 * 사원 중에 급여가 4000 이상인 사원의 명단
SQL>SELECT eno, ename, sal FROM emp WHERE sal >= 4000;


 * 이름이 '문시현'인 사원의 정보
SQL>SELECT * FROM emp WHERE ename = '문시현';



 * 10번 부서 이외 부서 사원의 명단
SQL>SELECT * FROM emp WHERE dno != '10';




WHERE 절에는 컬럼을 대상으로 조건을 기술해서 테이블의 행중 원하는 행만을 검색하는 기능을 담당, WHERE 절은 각각 검색 조건을 제공하여 검색되는 행을 제한함으로써 검색 결과의 효용성을 높임
조건을 기술 할 때에는 반드시 데이터 타입에 맞게 단일 인용 부호를 사용, 검색 컬럼이 문자, 날짜 일 경우 반드시 단일 인용 부호를 사용해야 하며, 조건에 사용되는 값들은 리터럴(문자)이므로 만일 조건의 내용이 영문일 경우 대소문자를 구별

-예제2. 잘못된 조건 검색
SQL>SELECT * FROM emp WHERE dno = 10;


-예제3. 연봉이 30,000 이상인 사원의 이름을 검색
SQL>SELECT eno, ename, sal*12+NVL(comm,0) FROM emp WHERE sal*12+NVL(comm,0) >=30000;

조건에는 컬럼 뿐 아니라 컬럼을 대상으로 한 수식이 가능

-예제4. 보너스가 200 이하인 사원을 검색
SQL>SELECT eno, ename, comm FROM emp WHERE comm <= 200;


SQL> SELECT eno, ename, comm FROM emp WHERE NVL(comm,0) <=200;


조건 대상인 컬럼의 값 중에 널이 있다면 사용한 연산자나 수식 등에 따라 결과의 신뢰도가 손상될 가능성이 있음

-예제5. 입사일이 1996년 이후인 사원의 정보 검색
SQL> SELECT * FROM emp WHERE hdate > '1995/12/31';


SQL>ALTER SESSION SET nls_date_format='YYYY/MM/DD';
이 명령어로 세션이 변경되어 날짜 출력시 YYYY/MM/DD 형태로 출력이 가능 하게 함

> 널과 비교 연산
* 널은 결정된 값이 아님으로 '=', '<' 등의 비교 연산자를 사용 할 수 없음
* 널에 대한 직접적인 검색은 다음과 같이 특별한 연산자 이용
 - IS NULL : 널 검색
 - IS NOT NULL : 널이 아닌 값을 검색

-예제6. 보너스 컬럼이 널인 사원을 검색
SQL>SELECT * FROM emp WHERE comm IS NULL;



널을 직접 검색하는 경우도 드물지만 직접 검색하기 위해서는 널 전용 연산자를 이용

<문제>
1. 1학년 학생의 성적을 학과별 성적순으로 검색
SELECT * FROM student WHERE syear = 1 ORDER BY avr;



2. 학과 및 학년별로 학점이 2.0 미만인 학생을 낮은 성적순으로 검색
SELECT * FROM student WHERE avr < 2.0 ORDER BY major, syear, avr;


3. 학과별로 정교수만을 검색
SELECT * FROM professor WHERE orders = '정교수' ;


4. 학과별로 부임일이 1998년 이전인 교수의 정보를 부임일 순으로 검색
SELECT * FROM professor WHERE hiredate <= '1998/01/01' ORDER BY hiredate;



5. 담당 교수가 정해지지 않은 과목을 학점 순으로 검색
SELECT * FROM course WHERE pno IS NULL ORDER BY st_num;



6. 보너스가 급여의 10% 이상인 사원을 검색
SELECT * FROM emp WHERE comm >= (0.1*sal);


5. 관계 연산자와 LIKE 연산자

> 관계 연산자
SQL> SELECT [DISTINCT | ALL] 컬럼, 컬럼 ...
  2     FROM 테이블
  3     WHERE 조건 [ 관계 연산자 조건 ...]
  4     ORDER BY 컬럼 [ASC/DESC], 컬럼 [ASC/DESC]...

* 관계 연산자는 여러 개의 조건을 동시에 이용 할 때 사용
* AND, OR, NOT 등의 관계 연산자가 이용
* 복잡한 관계 연산자는 예상치 못한 결과를 발생 시키며 두 개 이상의 관계 연산자를 이용 할 때는 반드시 괄호를 이용해서 연산의 우선순위를 SQL 작성자가 직접 결정

논리곱을 의미하는 AND는 주어진 조건이 모두 참인지를 확인하는 논리 연산자
OR 연산자는 주어진 복수의 조건 중에 적어도 하나 이상이 참인지를 확인하는 논리 연산자

-예제1. 다음 각 조건에 맞는 데이터를 검색
* 20번 부서 사원 중에 급여가 2000 이상인 사원을 검색
SQL>SELECT * FROM emp
  2    WHERE dno = '20'
  3     AND sal >= 2000;


SQL>SELECT * FROM emp WHERE dno = '20' AND sal >= 200 AND job = '모델링';



연산자가 한 문장에 여러개 사용 될 때는 우선순위에 의해 AND가 먼저 연산되고 OR이 나중에 연산됨

-예제2. 다음 두 문장을 실행하고 결과를 해석해
SQL> SELECT * FROM emp WHERE dno=10 OR sal > 1600 AND comm > 600;


SQL> SELECT * FROM emp WHERE (dno=10 OR sal > 1600) AND comm > 600;


괄호를 사용하면 연산자의 우선순위를 바꾸어 사용 가능

> LIKE 연산자
SQL> SELECT [ DISTINCT | ALL ] 컬럼, 컬럼 ....
  2     FROM 테이블
  3     WHERE 컬럼 LIKE '비교 문자열'
  4     ORDER BY 컬럼 [ASC/DESC], 컬럼 [ASC/DESC] .....

* WHERE 절에 사용되는 문자 전용의 비교 연산자
* 문자열의 일부만으로 검색하는 경우 사용
* 문자열에서 패턴을 찾아주는 연산자
* 두 개의 와일드 문자를 이용
 '-' : 반드시 한 개의 문자를 대체
 '%' : 문자열을 대체함 ( 문자가 없는 경우도 포함 )
* 와일드 문자 자체를 검색하는 경우 ESCAPE 절을 이용


-예제3. 다음 조건에 맞는 사원을 검색
* 김씨 성을 가진 사원
SQL> SELECT * FROM emp
  2     WHERE ename LIKE '김%';



* 이름이 '하늘'인 사원
SQL> SELECT * FROM emp 
  2     WHERE ename LIKE '%하늘';



* 성과 이름이 각각 한 글자인 사원을 검색
SQL>SELECT * FROM emp
  2    WHERE ename LIKE '__';


문자열의 일부분을 기억 할 때 사용하는 연산자 LIKE, 특히 컬럼의 데이터가 문자형이라면 대부분 LIKE를 통해 검색

▲ LIKE를 사용할 때 빈번한 실수
SQL> SELECT * FROM emp 
  2      WHERE ename = '김%';


처음 LIKE를 사용할 경우 흔히 저지르는 실수이지만 입문자들에게 잘 보이지 않음, 결과는 ' 선택된 레코드가 없습니다.' 로 에러는 아니다, 차라리 에러라면 찾기 쉽겠지만, 이때 '%'는 와일드 카드가 아니라 일반 문자로 해석

-예제4 이름에 '%' 문자가 포함된 사원을 검색
SQL>SELECT eno, ename 
  2    FROM emp 
  3    WHERE ename LIKE '%#%%' ESCAPE '#';

'%'나 '_'은 와일드 문자로 사용됨으로 이들 문자를 검색하는 경우 특별한 조치가 필요 이들 문자는 와일드 문자로 해석되기 때문에 조건에 직접 기술하는 경우 문자열이나 문자를 대치하는 와일드 문자로 해석되기 때문, 이를 방지하기 위해 ESCAPE절을 이용, ESCAPE 절을 이용하면 와일드 문자를 해석하지 않고 일반 문자로 인식, 예제 4와 같이 '#'을 ESCAPE 문자로 지정하면 '#' 문자 뒤에 기술된 '%'나 '_'은 와일드 문자가 아니라 일반 문자로 인식, 조건에 기술된 '%#%%'에서 첫 번째와 마지막 '%'은 와일드 문자로 해석되고 '#'뒤의 '%'는 일반 문자로 해석되어 ename 컬럼에 '%'가 포함된 행을 검색

<문제>
1. 화학과 학생 중에 성이 '사마'인 학생을 검색
SQL>SELECT sname, major 
  2    FROM student 
  3    WHERE sname LIKE '사마%' AND major = '화학';



2. 화학과 학생 중 4.5 환산 평점이 3.5 이상인 학생을 검색
SQL>SELECT major, sname, avr*(1.125) 
  2    FROM student
  3    WHERE avr*(1.125) >= 3.5 AND major = '화학';

-값이 없음-
조건을 화학을 없애고 조회해 봄


3. 화학과 이외 학과 학생의 평점을 각 학과 및 학년별로 검색
SQL>SELECT major, syear, sname, avr 
  2    FROM student 
  3    WHERE major != '화학' ORDER BY major, syear;



4. 교수가 정해진 과목 중에 화학 관련 과목을 검색(이름에 '화학'이란 문자열이 있는 과목)
SQL>SELECT * 
  2    FROM course 
  3    WHERE cname LIKE '%화학%' AND pno IS NOT NULL;



5. 2000년 이후 부임한 교수 중에 직위가 부교수인 교수를 검색
SQL>SELECT * 
  2    FROM professor 
  3    WHERE hiredate > '1999/12/31' AND orders LIKE '부교수';





6. BETWEEN와 IN 연산자

>BETWEEN.. AND 연산자
SQL>SELECT [DISTINCT | ALL] 컬럼, 컬럼 ...
  2    FROM 테이블
  3    WHERE 컬럼 BETWEEN 값1 AND 값2
  4    ORDER BY 컬럼 [ASC/DESC], 컬럼 [ASC/DESC] ...

 * '컬럼 >= 값1 AND 컬럼 <= 값2' 와 동일
 * 컬럼의 값이 값1에서 값2 사이의 값을 검색
 * 값1은 반드시 값2보다 작아야 함
 * AND 연산자로 환원 가능하지만 읽기 쉽기 때문에 BETWEEN..AND를 사용하는 것이 좋음

-예제1. 다음 조건에 맞는 사원을 검색
 * 급여가 1000에서 2000 이내인 사원
 * 10, 20번 부서 사원
SQL>SELECT * FROM emp
  2     WHERE sal BETWEEN 1000 AND 2000;



SQL>SELECT * FROM emp
  2    WHERE dno BETWEEN '10' AND '20';


BETWEEN.. AND.. 구문은 일정 범위의 값을 검색하는 방법으로 AND와 부등호를 이용한 표현에 비해서 가독성이 매우 뛰어남 WHERE sal BETWEEN 1000 AND 2000 을 관계 연산자로 표현한다면 WHERE sal >= 1000 AND sal <= 2000 과 같이 표현 가능하지만 가독성이 떨어지므로 가능한 BETWEEN 연산자를 이용하는 것이 좋음, BETWEEN 연산자가 제시한 값을 포함한다는 사실만 기억한다면 사용이 어렵지 않을 것

-예제2. 1992년에서 1996년 사이에 입사한 사원 검색
SQL>SELECT * FROM emp
  2    WHERE hdate BETWEEN '1992/01/01' AND '1996/12/31'
  3    ORDER BY hdate;


BETWEEN 연산이나 비교 연산의 대상이 날짜 타입인 경우 주의가 필요, 날짜 형 데이터는 화면에 표시할 때 '년/월/일' 만 표시하지만 내부적으로 '시:분:초'를 포함하기 때문에 조건문에 날짜를 쓸 때 '시:분'초'를 지정하지 않으면 기본 값은 0시 0분 0초인 '00:00:00'이 사용되는 데 이럴 경우 위의 예제의 조건을 풀어쓰면 1992년 1월 1일 0시 0분 0초에서 1996년 12월 31일 0시 0분 0초 까지 검색하게 됨. 만일 입사일이 1996년 12월 31일 11시 20분 30초 인 사원이 있다면 검색되지 않을 수 있음 따라서 화면에 표시되는 날짜 형식에 시 분초를 포함하고 싶다면 앞에서 설명한 ALTER 명령을 이용

ALTER SESSION SET nls_date_format = 'YYYY/MM/DD:HH24:MI:SS'

-예제3. 급여가 2000에서 1000 사이인 사원을 검색
SQL>SELECT * FROM emp
  2    WHERE sal BETWEEN 2000 AND 1000;

 BETWEEN 연산자를 이용 할 때 주의할 것은 작은 값이 먼저 와야 한다는 것, 위치가 바뀌면 '선택된 레코드가 없습니다.'란 정상 검색결과가 나오므로 주의!

▲어이없는 실수
 SQL문에서 간혹 어이 없는 실수가 발생하는 데  '... WHERE val BETWEEN -3 and -4 ; 같은 경우 작은 수가 -4 이기에 -4가 앞에 와야 함

> IN 연산자
SQL>SELECT [DISTINCT | ALL] 컬럼, 컬럼...
   2   FROM 테이블
   3   WHERE 컬럼 IN (값1, 값2 ...)
   4   ORDER BY 컬럼 [ASC/DESC], 컬럼[ASC/DESC] ..

* 지정된 값 중에 일치하는 값이 하나라도 있으면 검색 가능
* OR 연산자와 = 연산자로 교환 가능
* 가독성이 매우 우수
* IN 연산자는 나중에 서브 쿼리, 파티션 등의 여러 기능에 사용되는 중요한 연산자

-예제4. 다음 조건에 맞는 사원을 검색
 * 개발이나 관리 업무를 담당하는 사원
 * 10, 20번 부서 사원

SQL>SELECT * FROM emp
  2    WHERE job IN ('개발', '관리')
  3    ORDER BY job;


SQL>SELECT * FROM emp
  2    WHERE dno IN ('10', '20')
  3    ORDER BY dno;


IN 연산자는 모두 OR 연산자와 = 연산자로 교환 할 수 있음, 이렇게 바꾸어 기술하면 가독성이 현저히 떨어짐

-예제5. 결과가 동일한 두 개의 SQL문을 비교해 보자
SQL>SELECT * FROM emp
  2    WHERE dno BETWEEN '10' AND '20'
  3    AND job = '개발';



SQL> SELECT * FROM emp
  2     WHERE dno IN ('10', '20')
  3      AND job = '개발';


동일한 두 개의 결과를 만들기 위해 오라클은 서로 다른 두 개의 작업을 수행

<문제>
1. 평점이 3.0에서 4.0 사이의 학생을 학과별로 검색
SQL>SELECT * FROM student
  2    WHERE avr BETWEEN '3.0' AND '4.0'
  3    ORDER BY major;



2. 물리, 화학과 학생 중 4.5 환산 평점이 3.5에서 4.0 사이인 학생을 검색
SQL>SELECT sname, major, avr*(1.125)
  2    FROM student
  3    WHERE major IN ('물리','화학') AND avr*(1.125) BETWEEN 2.0 AND 4.0;
(4.5 환산 평점 3.0 이상 4.0 이하는 값이 없어 2.0으로 수정하여 검색함)


3. 물리, 화학과 학생의 정보를 학년별 성적순으로 검색
SQL>SELECT syear, avr, sname, major
  2    FROM student
  3    WHERE major IN ('물리','화학')
  4    ORDER BY syear, avr;



4. 물리, 화학과 교수 중에 1999년에서 2000년 사이에 부임한 교수의 정보를 직위별로 검색
SQL>SELECT orders, pname, hiredate
  2    FROM professor
  3    WHERE section IN ('물리', '화학') AND
  4    hiredate BETWEEN '1999/01/01' AND '2000/12/31'
  5    ORDER BY orders;





댓글 없음:

댓글 쓰기