WHERE 조건절 개요
자료를 검색할 때 SELECT 절과 FROM 절만을 사용하여 기본적인 SQL 문장을 구성한다면, 테이블에 있는 모든 자료들이 결과로 출력되어 실제로 원하는 자료를 확인하기 어렵다. 사용자들은 자신이 원하는 자료만을 검색하기 위해서 SQL 문장에 WHERE 절을 이용하여 검색되는 자료의 범위를 제한할 수 있다.
WHERE 절에는 두 개 이상의 테이블 조인 조건을 기술하거나 결과 제한을 위한 조건을 기술할 수 있다. 현실 DB는 많은 사용자, 프로그램이 동시에 접속해 다량의 트랜잭션을 발생시키는데, WHERE 조건절을 사용하지 않고 필요없는 많은 자료들을 DB로부터 요청하는 SQL 문장은 대량의 데이터를 검색할 때 DB가 설치된 서버의 CPU나 메모리 등의 시스템 자원을 과다 사용하게 된다. 또 많은 사용자들의 QUERY를 바로바로 처리하지 못하고, 검색된 많은 자료들이 네트워크를 통해서 전달되는 과정에 문제를 발생시킨다.
이런 문제의 방지를 위해 WHERE 절에 조건이 없는 FTS(Full Table Scan) 문장은 SQL 튜닝의 1차 검토 대상이 된다. (FTS가 무조건 나쁜 것은 아니며 병렬 처리 등을 이용해 유용하게 사용하는 경우도 많다.) 기본적인 SQL 문장은 Oracle의 경우 필수적으로 SELECT 절과 FROM 절로 이루어져 있다. SQL Server, Sybase 문장은 SELECT 목록에 상수, 변수 및 산술식(열 이름 없이)만 포함되는 경우에는 FROM 절이 필요 없지만, 테이블의 칼럼이 사용된 경우는 FROM 절이 필요하다. WHERE 절은 조회하려는 데이터에 특정 조건을 부여할 목적으로 사용하기 때문에 FROM 절 뒤에 온다.
SELECT [DISTINCT/ALL] 칼럼명 [ALIAS명] FROM 테이블명 WHERE 조건식;
WHERE 절은 FROM 절 다음에 위치하며, 조건식은 아래 내용으로 구성된다.
칼럼명 (보통 조건식 좌측 위치) - 비교 연산자 - 문자/숫자/표현식 (보통 조건식 우측 위치) - (조인 사용시)비교 칼럼명
연산자의 종류
비교 연산자
문자 유형간의 비교 조건이 발생하는 경우는 아래와 같이 처리한다.
[예제] 포지션이 미드필더(MF)인 선수의 이름과 백넘버, 키를 출력한다.
SELECT PLAYER_NAME 선수명, BACK_NO 백넘버, HEIGHT 키 FROM PLAYER WHERE POSITION='MF';
SQL 연산자
SQL 연산자는 SQL 문장에서 사용하도록 기본적으로 약속된 연산자로 모든 데이터 타입에 대해서 연산이 가능하다.
IN (list) 연산자
IN 문은 "OR"의 의미를 가지고 있어서 한 조건만 만족해도 조회가 가능하다. 예를 들어 JOB이 "CLERK"이거나 "MANAGER"인 것을 조회할 때 "JOB IN ('CLERK', 'MANAGER')"를 사용한다.
[예제] 팀ID가 K02이거나 K07인 선수의 이름과 포지션, 백넘버, 키를 출력한다.
[예제] 사원 테이블에서 JOB이 MANAGER이면서 20번 부서에 속하거나, JOB이 CLERK이면서 30번 부서에 속하는 사원의 정보를 IN 연산자의 다중 리스트를 이용해 출력하라.
사용자들이 잘 모르고 있는 다중 리스트를 이용한 IN 연산자는, SQL 문장을 짧게 만들어 주면서도 성능 측면에서도 좋은 매우 유용한 연산자이므로 적극 사용하자. 다만 아래 SQL 문장과는 결과가 다르므로 용도를 구분해서 사용해야 한다.
위의 쿼리는 "(MANAGER and 20번 부서 직원) or (CLERK and 30번 부서 직원)"의 리스트를 출력하지만 아래 쿼리는 "((MANAGERor CLERK) and (20번 or 30번 부서의 직원))"의 리스트를 출력한다.
LIKE 연산자
LIKE문은 와일드카드를 사용해 데이터를 조회할 수 있다. 와일드카드를 사용하지 않으면, 그 의미는 '='와 같다.
ex1) '강%'는 '강'으로 시작하는 모든 문자를 조회한다.
ex2)'test_'는 'test1', 'test2' 등 'test'로 시작하며 그 뒤에 한 글자가 더 붙은 문자열을 조회한다.
[예제] “장”씨 성을 가진 선수들의 정보를 조회하는 쿼리를 LIKE 연산자를 통해 작성해라.
BETWEEN a AND b 연산자
BETWEEN문은 지정된 범위에 있는 값을 조회한다. 이 때 a와 b의 값도 포함한다.
[예제] 키가 193cm 이상 195cm 이하인 선수들의 정보를 BETWEEN a AND b 연산자를 사용하여 조회하라.
IS NULL 연산자와 NULL 관련 함수
NULL(ASCII 00)은 값이 존재하지 않는 것으로 확정되지 않은 값을 표현할 때 사용한다. 따라서 어떤 값보다 크거나 작지도 않고 ‘ ’(공백, ASCII 32)이나 0(Zero, ASCII 48)과 달리 비교 자체가 불가능한 값이다. NULL의 연산 관련특성은 다음과 같다.
- NULL 값과의 수치연산은 NULL 값을 리턴한다.
- NULL 값과의 비교연산은 거짓FALSE을 리턴한다.
- 어떤 값과 비교할 수도 없으며, 특정 값보다 크다, 적다라고 표현할 수 없다.
따라서 NULL 값의 비교 연산은 IS NULL, IS NOT NULL 이라는 정해진 문구를 사용해야 제대로 된 결과를 얻을 수 있다.
또 NULL 관련 함수도 있다.
NULL 함수 | 예시 |
NVL() | NVL(MGR, 0): MGR 칼럼이 NULL이면 0으로 바꾼다. |
NVL2() | NVL2(MGR, 1, 0): MGR 칼럼이 NULL이 아니면 1을, NULL이면 0을 반환한다. |
NULLIF() | NULLIF(n1, n2): n1과 n2가 같으면 NULL을, 같지 않으면 n1을 반환한다. |
COALESCE() | COALESCE(mgr, 1): mgr이 NULL이 아니면 1을 반환한다. |
[예제 및 실행 결과]
실행 결과로 선택된 레코드가 없다는 메시지가 출력되었다. WHERE 절에서 POSITION = NULL을 사용했는데 문법 에러가 나지는 않았지만 WHERE 절의 조건이 거짓이 되어 WHERE 절의 조건을 만족하는 데이터를 한건도 얻지 못한, 의미 없는 SQL이 되고 말았다.
[예제] POSITION 칼럼 값이 NULL 값인지 판단하기 위해서는 IS NULL을 사용하여 다음과 같이 수정하여 실행한다.
반대로 NULL값이 아닌 레코드를 조회하고 싶다면 'IS NULL' 대신 'IS NOT NULL'을 사용한다.
논리 연산자
논리 연산자는 비교 연산자나 SQL 비교 연산자들로 이루어진 여러 조건들을 논리적으로 연결시키기 위해 사용한다.
[예제] “소속이 삼성블루윙즈”인 조건과 “키가 190cm 이상”인 자료를 조회해보자. 조건을 연결해 보면 “소속이 삼성블루윙즈이고 키가 170cm 이상인 조건을 가진 선수"들의 자료를 조회하는 것이다.
[예제] 다음 조건을 만족하는 선수의 선수이름, 포지션, 백넘버, 키를 출력한다.
조건) 소속팀이 삼성블루윙즈이거나 전남드래곤즈에 소속되었으며, 포지션이 미드필더(MF)이다. 키는 180cm 이상, 190cm 이하이다.
실행 결과의 내용을 보면 포지션이 미드필더가 아닌 선수들의 명단도 출력되었다. 괄호가 누락되어 OR 논리 연산자보다 AND 논리 연산자를 먼저 실행했기 때문이다. 논리 연산자들이 여러 개가 같이 사용되었을 때의 처리 우선순위는 ( ), NOT, AND, OR의 순으로 처리된다.
논리 연산자의 우선 순위를 고려하여 다시 출력해보자.
TEAM_ID 조회를 IN 연산자를 사용하고, HEIGHT 조회는 BETWEEN 대신 >=, <=, AND를 사용해서 짠 쿼리이다. 당연히 결과는 같다.
부정 연산자
비교 연산자, SQL 비교 연산자에 대한 부정 표현을 부정 논리 연산자, 부정 SQL 연산자로 구분할 수 있다.
[예제] 삼성블루윙즈 소속인 선수들 중에서 포지션이 미드필더가 아니고, 키가 175cm 이상 185cm 이하가 아닌 선수들의 자료를 찾아본다.
[예제] 국적(NATION) 칼럼의 경우 내국인들은 별도 데이터를 입력하지 않았다. 국적 칼럼이 NULL이 아닌 선수와 국적을 표시하라.
ROWNUM, TOP 사용
ROWNUM - Oracle
Oracle의 ROWNUM은 칼럼과 비슷한 성격의 Pseudo Column으로, SQL 처리 결과 집합의 각 행에 대해 임시로 부여되는 일련번호이며, 테이블이나 집합에서 원하는 만큼의 행만 가져오고 싶을 때 WHERE 절에서 행의 개수를 제한하는 목적으로 사용한다.
한 건의 행만 가져오고 싶을 때는 아래와 같이 사용할 수 있다.
SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM = 1;
SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM <= 1;
SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM < 2;
두 건 이상의 N 행을 가져오고 싶을 때는 ROWNUM = N; 처럼 사용할 수 없다. 아래처럼 <=를 사용한다.
SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM <= N;
추가적인 ROWNUM의 용도로는 테이블 내의 고유한 키나 인덱스 값을 만들 수 있다.
UPDATE MY_TABLE SET COLUMN1 = ROWNUM;
TOP 절 - SQL Server
SQL Server는 TOP 절을 사용하여 결과 집합으로 출력되는 행의 수를 제한할 수 있다. TOP 절의 표현식은 다음과 같다.
TOP (Expression) [PERCENT] [WITH TIES]
- Expression : 반환할 행의 수를 숫자로 지정한다.
- PERCENT : 쿼리 결과 집합에서 처음 Expression%의 행만 반환됨을 나타낸다.
- WITH TIES : ORDER BY 절이 지정된 경우에만 사용할 수 있으며, TOP N(PERCENT)의 마지막 행과 같은 값이 있는 경우 추가 행이 출력되도록 지정할 수 있다.
한 건의 행만 가져오고 싶을 때는 아래처럼 사용한다.
SELECT TOP(1) PLAYER_NAME FROM PLAYER;
두 건 이상의 N 행을 가져오고 싶을 때는 아래처럼 처럼 출력되는 행의 개수를 지정한다.
SELECT TOP(N) PLAYER_NAME FROM PLAYER;
SQL 문장에서 ORDER BY 절이 사용되지 않으면 Oracle의 ROWNUM과 SQL Server의 TOP 절은 같은 기능을 하지만, ORDER BY 절이 같이 사용되면 기능의 차이가 발생한다. 이 부분은 ORDER BY 절에서 설명하도록 한다.
'SQLD > SQL 기본 및 활용' 카테고리의 다른 글
3-7 GROUP BY, HAVING 절 (0) | 2020.02.28 |
---|---|
3-6 FUNCTION (0) | 2020.02.28 |
3-4 TCL (0) | 2020.02.28 |
3-3 DML (0) | 2020.02.28 |
3-2 DDL (0) | 2020.02.27 |