본문 바로가기
IT 이론/데이터베이스

[데이터베이스] SELECT Statement

by 지식id 2012. 11. 12.
반응형

SELECT (ALL | DISTINCT) target_list
(INTO host_var_list)
FROM table_expression
WHERE 조건
(GROUP BY 집단화 애트리뷰트 (HAVING 집단 조건))
(ORDER BY 애트리뷰트 목록)
(LIMIT {count (OFFSET offset) | offset, count})

 

LIMIT과 OFFSET은 SQL 표준 키워드는 아니다. 하지만 Mysql, Oracle을 비롯한 대부분의 상용 DBMS에서 사용되고 있다.

 

아래는 각 절별 실행 우선순위 이다.

 

 SELECT 문의 실행 순서
 SELECT  5
 FROM  1
 WHERE  2
 GROUP BY  3  HAVING

 4

 ORDER BY

 6

 LIMIT  7

 

FROM에 있는 테이블선택

WHERE절에 있는 조건에 해당하는 튜플 검색

GROUP BY대로 튜플 그룹화, HAVING

조건에 맞게 선택되고 그룹화된 튜플들 중 명시된 애트리뷰트 선택

ORDER BY 에 있는 순서대로 sorting

정렬된 튜플들을 LIMIT의 조건대로 자름

 

즉, SELECT절에 명시된 조건을 FROM절이나 WHERE절에서 인식 할 수 없다. 무슨말인고 하니

 

  1. //아래와 같은 SQL문은 오류를 발생시킨다.
  2. SELECT NAME as n FROM EMPLOYEE WHERE n='Raisonde';
  3.  
  4. //SELECT의 우선순위가 ORDER BY보다 높으므로 아래와 같이는 사용가능하다.
  5. SELECT (SALARY+BONUS) as pay FROM EMPLOYEE WHERE dno='2' ORDER BY pay;
  6.  

 

 

SELECT문은 기본적으로 조건에 맞는 결과를 출력 해 주는 용도로, 그 조건을 정하는 WHERE절의 사용이 중요하다. 아래는 WHERE절의 사용 예.

 

  1. SELECT * FROM EMPLOYEE WHERE name = 'Raisonde';
  2.  
  3. //아래 두 문은 같다.
  4. SELECT * FROM EMPLOYEE WHERE NOT number = 20;
  5. SELECT * FROM EMPLOYEE WHERE NOT number <> 20;
  6.  
  7. //아래 두 문은 같다.(괄호 사용 가능. 일반적인 수학 이론대로 적용된다.)
  8. SELECT * FROM EMPLOYEE WHERE NOT (name = 'Park' OR dept_no = 10);
  9. SELECT * FROM EMPLOYEE WHERE name <> 'Park' AND dept_no <> 10;
  10.  
  11. //아래 두 문은 같다.(BETWEEN 연산자)
  12. SELECT * FROM EMPLOYEE WHERE number BETWEEN 10 AND 20 AND dept_num NOT BETWEEN 5 AND 30;
  13. SELECT * FROM EMPLOYEE WHERE number > 10 AND number < 20 AND dept_num < 5 AND dept_num > 30;

 

 

SELECT문은 JOIN연산을 지원한다. FROM절에 여러 테이블을 넣을 수 있다.

 

  1. //SELECT에 명시된 애트리뷰트가 FROM절에 명시된 테이블들에 동시에 존재하는 이름이 아니라면 그대로 사용 가능하다.
  2. SELECT FNAME, LNAME, ADDRESS FROM EMPLOYEE, DEPARTMENT
  3. WHERE DNAME='Research' AND DNUMBER=DNO;
  4.  
  5. //하지만 그렇게 할 경우 해당 애트리뷰트가 어떤 테이블에 있는 것인지 햇갈리므로 점(".")을 이용해 지정 해 주는 것이 좋다. (추후에 EMPLOYEE에 DNAME이라는 애트리뷰트가 생겨도 오류가 나지 않는다.)
  6. SELECT EMPLOYEE.FNAME, LNAME, ADDRESS FROM EMPLOYEE, DEPARTMENT
  7. WHERE DEPARTMENT.DNAME='Research' AND DEPARTMENT.DNUMBER=EMPLOYEE.DNO ;
  8.  
  9. //테이블 명을 전부 사용하면 너무 길어서 적기도 보기도 힘드므로 아래와 같이 tuple variable을 이용하면 깔끔하다. 위 2개의 문을 비롯한 3가지 문은 모두 똑같이 정상작동 되나 아래 예가 가장 바람직한 예이다.
  10. SELECT e.FNAME, e.LNAME, e.ADDRESS FROM EMPLOYEE e, DEPARTMENT d
  11. WHERE d.DNAME='Research' AND d.DNUMBER=e.DNO;

 

 

이론상에선 질의 내에서 Tuple variable을 사용할 때 애트리뷰트들을 재명명 해 줄 수 있다.

 

  1. //하지만 Mysql이나 Oracle들 많은 상용 DBMS에선 이를 지원하지 않는다.
  2. SELECT e.a FROM EMPLOYEE e(a,b,c,d,e,f,g);
  3.  
  4. //아래와 같은 문은 대부분은 상용 DBMS에서 정상적으로 작동한다.
  5. SELECT e.NAME FROM EMPLOYEE e;

 

 

JOIN연산은 Cartesian Production이다. 즉, 조건에 해당하는 테이블들의 모든 애트리뷰트들의 Cross 곱이 표시된다.

 

  1. //아래와 같은 SELECT문을 실행하면 Research부서에 속한 모든 EMPLOYEE의 애트리뷰트와, DEPARTMENT테이블에 있는 Research부서 모든 정보들이 출력될 것이다.
  2. //Research부서는 한개이고, 그에 속한 직원은 여러명이기 때문에 Cartesian Product를 하면 Research부서의 정보들은 직원들의 수만큼 여러번 출력된다.
  3. SELECT * FROM EMPLOYEE, DEPARTMENT
  4. WHERE DNAME='Research' AND DNO=DNUMBER ;
  5.  
  6. //아래와 같은 SELECT문을 실행하면 (직원의 수)*(부서의 수)만큼의 결과값이 출력된다. WHERE절이 생략되어 조건이 없으므로 모든 직원과 모든 부서의 조합이 다 출력된다.
  7. SELECT * FROM EMPLOYEE, DEPARTMENT;

 

 

SELECT문의 결과는 SET이 아니다. WHERE절에 따라 같은 결과가 여러번 출력 될 수도 있다.

 

  1. //예를 들어, 대구에서 어떤 프로젝트를 수행하는 부서를 찾고 싶을때, 대구에서 수행되고 있는 프로젝트가 여러개고, 그 중 몇개를 어떤 한 부서에서 맡고 있다면 그 부서는 여러번 출력 될 것이다.
  2. SELECT d.DNAME FROM DEPARTMENT d, PROJECT p WHERE p.LOCATION = '대구' and p.DNO=d.DNUMBER;
  3.  
  4. //위 결과값에서, 대구에서 수행되고 있는 프로젝트를 하나만이라도 가지고 있는 부서를 중복 없이 출력하고 싶다면 아래와 같이 할 수 있다. (DISTINCT 키워드 추가)
  5. SELECT DISTINCT d.DNAME FROM DEPARTMENT d, PROJECT p WHERE p.LOCATION = '대구' and p.DNO=d.DNUMBER;

 

*[데이터베이스]로 분류된 포스팅에 포함된 문들을 오타가 있을 수 있으며 특정 DBMS에서 테스트되지 않았습니다. 그냥 이론으로만 참고 하세요. 데이터베이스 내용은 박영철 교수님의 수업 자료를 바탕으로 하고 있으며, 그대로 차용된 설명 내용이나 예제가 있으니 맘대로 퍼가시면 안됩니다~

반응형

댓글