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절에서 인식 할 수 없다. 무슨말인고 하니
-
//아래와 같은 SQL문은 오류를 발생시킨다.
-
SELECT NAME as n FROM EMPLOYEE WHERE n='Raisonde';
-
-
//SELECT의 우선순위가 ORDER BY보다 높으므로 아래와 같이는 사용가능하다.
-
SELECT (SALARY+BONUS) as pay FROM EMPLOYEE WHERE dno='2' ORDER BY pay;
-
SELECT문은 기본적으로 조건에 맞는 결과를 출력 해 주는 용도로, 그 조건을 정하는 WHERE절의 사용이 중요하다. 아래는 WHERE절의 사용 예.
-
SELECT * FROM EMPLOYEE WHERE name = 'Raisonde';
-
-
//아래 두 문은 같다.
-
SELECT * FROM EMPLOYEE WHERE NOT number = 20;
-
SELECT * FROM EMPLOYEE WHERE NOT number <> 20;
-
-
//아래 두 문은 같다.(괄호 사용 가능. 일반적인 수학 이론대로 적용된다.)
-
SELECT * FROM EMPLOYEE WHERE NOT (name = 'Park' OR dept_no = 10);
-
SELECT * FROM EMPLOYEE WHERE name <> 'Park' AND dept_no <> 10;
-
-
//아래 두 문은 같다.(BETWEEN 연산자)
-
SELECT * FROM EMPLOYEE WHERE number BETWEEN 10 AND 20 AND dept_num NOT BETWEEN 5 AND 30;
-
SELECT * FROM EMPLOYEE WHERE number > 10 AND number < 20 AND dept_num < 5 AND dept_num > 30;
SELECT문은 JOIN연산을 지원한다. FROM절에 여러 테이블을 넣을 수 있다.
-
//SELECT에 명시된 애트리뷰트가 FROM절에 명시된 테이블들에 동시에 존재하는 이름이 아니라면 그대로 사용 가능하다.
-
SELECT FNAME, LNAME, ADDRESS FROM EMPLOYEE, DEPARTMENT
-
WHERE DNAME='Research' AND DNUMBER=DNO;
-
-
//하지만 그렇게 할 경우 해당 애트리뷰트가 어떤 테이블에 있는 것인지 햇갈리므로 점(".")을 이용해 지정 해 주는 것이 좋다. (추후에 EMPLOYEE에 DNAME이라는 애트리뷰트가 생겨도 오류가 나지 않는다.)
-
SELECT EMPLOYEE.FNAME, LNAME, ADDRESS FROM EMPLOYEE, DEPARTMENT
-
WHERE DEPARTMENT.DNAME='Research' AND DEPARTMENT.DNUMBER=EMPLOYEE.DNO ;
-
-
//테이블 명을 전부 사용하면 너무 길어서 적기도 보기도 힘드므로 아래와 같이 tuple variable을 이용하면 깔끔하다. 위 2개의 문을 비롯한 3가지 문은 모두 똑같이 정상작동 되나 아래 예가 가장 바람직한 예이다.
-
SELECT e.FNAME, e.LNAME, e.ADDRESS FROM EMPLOYEE e, DEPARTMENT d
-
WHERE d.DNAME='Research' AND d.DNUMBER=e.DNO;
이론상에선 질의 내에서 Tuple variable을 사용할 때 애트리뷰트들을 재명명 해 줄 수 있다.
-
//하지만 Mysql이나 Oracle들 많은 상용 DBMS에선 이를 지원하지 않는다.
-
SELECT e.a FROM EMPLOYEE e(a,b,c,d,e,f,g);
-
-
//아래와 같은 문은 대부분은 상용 DBMS에서 정상적으로 작동한다.
-
SELECT e.NAME FROM EMPLOYEE e;
JOIN연산은 Cartesian Production이다. 즉, 조건에 해당하는 테이블들의 모든 애트리뷰트들의 Cross 곱이 표시된다.
-
//아래와 같은 SELECT문을 실행하면 Research부서에 속한 모든 EMPLOYEE의 애트리뷰트와, DEPARTMENT테이블에 있는 Research부서 모든 정보들이 출력될 것이다.
-
//Research부서는 한개이고, 그에 속한 직원은 여러명이기 때문에 Cartesian Product를 하면 Research부서의 정보들은 직원들의 수만큼 여러번 출력된다.
-
SELECT * FROM EMPLOYEE, DEPARTMENT
-
WHERE DNAME='Research' AND DNO=DNUMBER ;
-
-
//아래와 같은 SELECT문을 실행하면 (직원의 수)*(부서의 수)만큼의 결과값이 출력된다. WHERE절이 생략되어 조건이 없으므로 모든 직원과 모든 부서의 조합이 다 출력된다.
-
SELECT * FROM EMPLOYEE, DEPARTMENT;
SELECT문의 결과는 SET이 아니다. WHERE절에 따라 같은 결과가 여러번 출력 될 수도 있다.
-
//예를 들어, 대구에서 어떤 프로젝트를 수행하는 부서를 찾고 싶을때, 대구에서 수행되고 있는 프로젝트가 여러개고, 그 중 몇개를 어떤 한 부서에서 맡고 있다면 그 부서는 여러번 출력 될 것이다.
-
SELECT d.DNAME FROM DEPARTMENT d, PROJECT p WHERE p.LOCATION = '대구' and p.DNO=d.DNUMBER;
-
-
//위 결과값에서, 대구에서 수행되고 있는 프로젝트를 하나만이라도 가지고 있는 부서를 중복 없이 출력하고 싶다면 아래와 같이 할 수 있다. (DISTINCT 키워드 추가)
-
SELECT DISTINCT d.DNAME FROM DEPARTMENT d, PROJECT p WHERE p.LOCATION = '대구' and p.DNO=d.DNUMBER;
*[데이터베이스]로 분류된 포스팅에 포함된 문들을 오타가 있을 수 있으며 특정 DBMS에서 테스트되지 않았습니다. 그냥 이론으로만 참고 하세요. 데이터베이스 내용은 박영철 교수님의 수업 자료를 바탕으로 하고 있으며, 그대로 차용된 설명 내용이나 예제가 있으니 맘대로 퍼가시면 안됩니다~
'IT 이론 > 데이터베이스' 카테고리의 다른 글
[데이터베이스] Transaction isolation level (0) | 2012.12.12 |
---|---|
[데이터베이스] 부질의(subquery), 중첩질의(nested query) (0) | 2012.11.30 |
[데이터베이스] INSERT, DELETE, UPDATE Statement (0) | 2012.11.11 |
[데이터베이스] Table Statement and Constraint (0) | 2012.11.11 |
[데이터베이스] User and Schema Management (0) | 2012.11.11 |
댓글