728x90
반응형


제 5절 WHERE 절


1. WHERE 조건절 개요


  자료를 검색할 때 SELECT 절과 FROM 절만을 사용하여 기본적인 SQL 문장을 구성한다면, 테이블에 있는 모든 자료들이 결과로 출력되어 실제로 원하는 자료를 확인하기 어려울 수 있다. 사용자들은 자신이 원하는 자료만을 검색하기 위해서 SQL 문장에 WHERE 절을 이용하여 자료들에 대한 제한을 할 수 있다.


SELECT [DISTINCT/ALL] 칼럼명 [ALIAS명]

FROM 테이블명

WHERE 조건식;


 이러한 형식으로 WHERE절을 이용한 조건적 SELECT문을 작성할 수 있다. 이와 같이 조건절은 FROM절 다음에 위치할 수 있으며, 조건식은 칼럼명, 비교연산자, 문자, 숫자, 표현식, 비교 칼럼명(JOIN 사용 시) 등이 나올 수 있다. 



2. 연산자의 종류


- 비교 연산자(부정 비교 연산자 포함)

- SQL 연산자(부정 SQL 연산자 포함)

- 논리 연산자



 비교 연산자와 논리연산자는 지금껏 접해본 연산자이고, SQL 연산자가 조금 생소 할 수 있다. 네가지 밖에 없으니 외우는 것이 좋겠다. 


- BETWEEN a AND b

- IN (list)

- LIKE '비교문자열'

- IS NULL 



 그리고 이것들의 연산자 우선순위는 아래와 같다. 모든 수식에서도 마찬가지로 괄호가 제일 우선인 순위를 가지고, 그다음에 NOT, 그다음에 비교연산자, 그 후에 중요하게 여겨지는 AND와 OR이다. 현실세계에서 데이터를 조회할 때 이 연산자 우선순위 중 AND와 OR을 고려하지 않아서 잘못된 조회가 발생될 수 있다. 


 이러한 연산에 있어서 연산자들의 우선순위를 염두에 두지않고 WHERE 절을 작성한다면 테이블에서 자기가 원하는 자료를 찾지 못하거나, 혹은 틀린 자료인지도 모른 채 사용할 수도 있다. 실수하기 쉬운 비교 연산자와 논리 연산자의 경우 괄호를 사용해서 우선순위를 표시하는 것을 권고한다고 한다.






3. 비교연산자


 비교연산자의 종류는 아래 표와 같다. 간단히 눈으로 훑어보기만 하면 될 것 같다. 그리고 주의해야할 점이, '=' 연산자를 사용할 때 CHAR 변수나 VARCHAR2와 같은 문자형 타입을 가진 칼럼을 특정 값과 비교하기 위해서는 인용부호(작은 따옴표, 큰 따옴표)로 묶어서 비교 처리를 해야 함을 잊지 말자.


 이와 다르게 NUMERIC과 같은 숫자형 형태의 값은 인용부호를 취하지 않아도 된다.





 추가적으로 문자 유형간의 비교 조건이 발생하는 경우는 다음 표와 같이 처리한다. 표에서 줄만 나눠놨지 단계라고 생각하면 될 것 같다. 여기서 주의해야 할 점은 문자 유형 칼럼의 경우 따옴표 표시가 없는 경우 에러가 발생할 수 있지만, 숫자 유형 칼럼의 경우 숫자로 변환이 가능한 문자열과 비교되면 상대 타입을 숫자 타입으로 바꾸어 비교해버린다. 


 예를들어 WHERE HEIGHT >= 170 이라는 조건을 WHERE HEIGHT >= '170' 이라고 바꾸어도 HEIGHT라는 칼럼이 숫자 유형의 변수이므로 내부적으로 '170' 라고 표시된 문자열을 숫자 유형 170으로 바꾸어 처리하기 때문에 문제가 전혀 되지 않는다. 





4. SQL 연산자


 다음은 제일 생소하게 여겨질 것 같은 SQL 연산자이다. SQL 문장에서 사용하도록 기본적으로 예약되어 있는 연산자로서 모든 데이터 타입에 대해서 연산이 가능한 4가지 종류가 있다. 아래 표를 참고하길 바란다.



 SQL 연산자의 종류는 필히 숙지해두고 있어야 하므로 예제를 통하여 학습을 하는 것이 좋을 것 같다. 아래 예시를 살펴보자.




- IN 연산자


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE TEAM_IN IN ('K02', 'K07');


 이 SQL 구문의 뜻을 살펴보자면, PLAYER라는 테이블에서 선수이름(별명), 포지션, 백넘버, 키라는 컬럼을 선택한다. 그러나 WHERE절의 조건을 적용하여 조회하게 되는데, 이 조건은 'K02' 나 'K07' 라는 값 들 중 하나라도 속하면 그 컬럼을 선택하여 조회하는 구문이다.


 이처럼 IN 이라는 연산자는 리스트에 있는 값중에서 어느 하나라도 일치하면 되는 것이다. 예시를 두가지 더 보자면


SELECT ENAME, JOB, DEPTNO

FROM EMP

WHERE (JOB, DEPTNO) IN (('MANAGER', 20), ('CLERK', 30));


 EMP라는 테이블에서 ENAME, JOB, DEPTNO 라는 컬럼을 조회하는데, 이 때 직업과 부서번호 칼럼 중에서 매니저,20 이라는 조건과 점원, 30 이라는 조건을 만족할 경우 출력하는 구문이다.


그러나 아래 구문을 보자.


SELETE ENAME, JOB, DEPTNO FROM EMP

WHERE JOB IN ('MANAGER', CLERK')

AND DEPTNO IN (20, 30);


 이 구문은 위 구문처럼 동일한 출력 결과를 내놓을 것인가? 결론부터 말하자면 아니고, 직업이 매니저인 사람들을 출력하고, 점원인 사람을 출력하고, 그 다음 20인 사람을 출력하고, 30인 사람을 출력하기 때문에, 즉 매니저이면서 30인 결과가 나올 수 있기 때문에 의도하지않은 출력결과가 나올 수 있다.




- LIKE 연산자


 LIKE 연산자는 '~와 같다'라는 의미이다. 단순히 LIKE 'MF' 라고 입력을 하게 되면 = MF 라는 연산자와 같은 기능을 할 수 있다. 그러나 만약 "장" 씨 성을 가진 선수들을 조회하거나, 이름이 "희"로 끝나는 사람을 조회할 때 쓸 수 있는 연산자는 LIKE이다. 이 때 LIKE연산자의 기능인 와일드카드(WildCard)를 쓸 수 있다. 


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE POSITION LIKE 'MF';



"장"씨 성을 가진 선수들의 정보를 조회하는 WHERE 절은 다음과 같다.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE PLAYER_NAME LIKE '장%';


'장%' 이라고 LIKE문을 작성하였을 경우 장땡땡, 장땡땡땡, 장땡땡땡땡의 이름을 검색할 수 있다. 

만약 %장%이라고 검색할 때 땡장땡, 땡땡장땡, 땡장땡땡 등의 이름을 검색할 수 있다. 그렇다면 %장 이라고 검색을 하면 땡장, 땡땡장, 떙땡땡장 이라는 검색 결과를 얻을 수 있다.


그렇다면 %가 아닌 _라는 와일드카드를 썼을 때 기대할 수 있는 결과를 알아보자면, 예를 들어 '_eo'라고 검색하면 seo, aeo, beo, ceo, ... 라는 검색결과를 얻을 수 있다. _는 1개인 단일 문자 어떤 것을 의미한다. 만일 '장_' 이라고 검색하면, 장땡, 장깽, 장쨍, 장뺑 등의 결과를 기대할 수 있다. 




- BETWEEN a AND b 연산자


SQL 연산자의 세번째 연산자로 이 연산자는 어떠한 값 사이에 있는 컬럼들을 조회할 때 유용한 연산자이다. 예를 들어 키가 170 센티미터 이상 180 센티미터 이하인 선수들의 정보를 조회한다고 할 때 다음과 같이 SQL 문을 짤 수 있다.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE HEIGHT BETWEEN 170 AND 180;


BETWEEN 170 AND 180 이라는 구문은 범위에서 'a'와 'b'의 값을 포함하는 범위를 말하는 것이다. 





- IS NULL 연산자


 NULL 은 값이 존재하지 않는 것으로 확정되지 않은 값을 표현할 때 사용한다. 따라서 어떤 값보다 크거나 작지도 않고 공백이나 0과 달리 비교 자체가 불가능한 값인 것이다. 연산 관련 NULL의 특성은 다음과 같다.


- NULL 값과의 수치 연산은 NULL 값을 리턴한다.

- NULL 값과의 비교 연산은 FALSE를 리턴한다.

- 어떤 값과 비교할 수도 없으며, 특정 값보다 크다, 적다라고 표현할 수 없다.


이와 같은 특성을 가지는 NULL은 비교연산자를 통해 비교할 수 없고, 만일 비교연산을 할 경우 false를 리턴하게 되어 제대로된 결과를 얻을 수 없다. 


예를 들어 아래와 같은 SQL 구문을 보자.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE POSITION = NULL;


이라는 구문을 조회했을 때, 비교연산자를 통해 NULL을 조회하였으므로 제대로된 SQL 구문을 생성할 수 없다. 포지션이 없는 선수들을 조회하는 제대로된 SQL 구문은 다음과 같다.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, TEAM_ID

FROM PLAYER

WHERE POSITION IS NULL;


이 때 IS NULL 연산자를 이용하여 데이터를 조회하면, 포지션값이 없는 선수들을 조회할 수 있다.






5. 논리연산자


 논리연산자는 비교연산자나 SQL 비교 연산자들로 이루어진 여러 개의 조건들을 논리적으로 연결시키기 위해서 사용되는 연산자라고 생각하면 된다. 아래와 같은 표를 보고 실제로 적용되는 예를 통해 사용법을 이해하도록하자.



예를 들어 소속이 삼성블루인즈인 조건과 키가 170센티미터 이상인 조건을 연결해보면 소속이 수원삼성블루윙즈이고 키가 170센티미터 이상인 조건을 가진 선수들의 자료를 조회하는 것이라고 할 수 있다. 


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER 

WHERE TEAM_ID = 'K02'

AND HEIGHT >= 170;


라고 데이터를 올바르게 검색 할 수 있다. 이와 같이 조건과 조건을 이을 때 논리 연산자를 사용하고 나머지 OR도 쓰임이 비슷하다. 


그러나 여기서 주의해야 할 점은 AND와 OR의 논리연산자 순서를 기억해야한다. 아래와 같은 예시를 보면, 포지션이 MF 인 연산자만 나와야 하는데, OR 연산자보다 AND 연산자들이 먼저 처리가 됬으므로 포지션이 MF가 아닌 결과값들이 나올 수 있다. 이러한 오류를 방지하기 위해서 보통 괄호를 이용하여 처리한다.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE TEAM_ID = 'K02' OR TEAM_ID = 'K07'

AND POSITION = 'MF'

AND HEIGHT >= 170

AND HEIGHT <=180;

SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE (TEAM_ID = 'K02' OR TEAM_ID = 'K07')

AND POSITION = 'MF'

AND HEIGHT >= 170

AND HEIGHT <=180;





6. 부정 연산자


 비교 연산자, SQL 비교 연산자에 대한 부정 표현을 부정 논리 연산자, 부정 SQL 연산자로 구분할 수 있다. 부정 연산자의 종류는 아래와 같다. 



삼성블루윙즈 소속인 선수들 중에서 포지션이 미드필더가 아니고 키가 175센티미터이상, 185센티미터 이하가 아닌 선수들의 자료를 찾고자 할 때 다음과 같이 SQL 구문을 작성한다.


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE TEAM_ID = 'K02'

AND NOT POSITION = 'MF'

AND NOT HEIGHT BETWEEN 175 AND 185;


위 SQL 구문과 같은 기능을 하는 SQL 구문은 다음과 같다. 


SELECT PLAYER_NAME 선수이름, POSITION 포지션, BACK_NO 백넘버, HEIGHT 키

FROM PLAYER

WHERE TEAM_ID = 'K02'

AND POSITION <> 'MF'

AND NOT HEIGHT BETWEEN 175 AND 185;





7. ROWNUM, TOP 사용


- 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;

-SELECT PLAYER_NAME FROM PLAYER WHERE ROWNUM < N+1; (출력되는 행의 한계를 지정)


추가적으로 ROWNUM의 용도는 테이블 내의 고유한 키나 인덱스 값을 만들 수 있다. 



- SQL Server의 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 절이 사용되지 않으면 ROWNUM과 SQL Server의 TOP절은 같은 기능을 하지만, 같이 사용될 경우 기능의 차이가 발생된다. (TOP 절이 기능이 더 좋음)




728x90
반응형