필터링 = 조건이다.
엑셀에서 "이런 값을 가진 데이터만 보고싶어" 할 때 필터기능을 쓰는걸 생각하자.
select
, update
, delete
문의 WHERE
절에서 사용할 수 있는 다양한 필터조건을 알아보자.
AND
나 OR
를 통해 하나 이상의 조건을 포함시킬 수 있다.값 = 조건
의 형태로 쓰자. WHERE NOT
은 <>
와 같다. WHERE NOT
(first_name = 'STEVEN' OR last_name = 'YOUNG')
AND create_date > '2006-01-01'
이 쿼리는 <>
를 이용하여 아래 쿼리처럼 쓸 수도 있다.
WHERE
first_name <> 'STEVEN'
AND last_name <> 'YOUNG'
AND create_date > '2006-01-01'
아래 쿼리가 사람이 이해하기에 좀더 쉽다.
→ first_name이 'steven'이 아닌 사람
그리고 last_name이 'young'이 아닌 사람
그리고 2006년 1월 1일 이후에 생성된
조건은 1개 이상의 연산자와 1개 이상의 표현식으로 구성된다.
Maple Street
)concat('Learning', ' ', 'SQL')
)('Boston','New York','Chicago')
)내장함수를 확인해보고 싶을 때는 아래와 같이 from dual
을 활용하면 된다.
예를 들어, concat
함수가 어떻게 작동하는지 궁금하다 하면
SELECT concat('Hello',' ','World!')
FROM DUAL;
=
, !=
, <
, >
, <>
, like
, in
, between
+
, -
, *
, /
=
연산자를 사용한다.
열 = 표현/값
!=
, <>
연산자를 사용한다.
동등/부등조건은 보통 데이터를 수정할 때 사용한다.
예를 들어, 오래된 계정을 삭제하는 정책이 있고, 그 때문에 rental 테이블에서 대여날짜가 2004년인 행을 삭제해야 한다고 가정해보자.
DELETE FROM rental
WHERE year(rental_date) = 2004 ;
혹은 대여날짜가 2005년이나 2006년이 아닌 행을 삭제해야 한다면?
DELETE FROM rental
WHERE year(rental_date) <> 2005
AND year(rental_date) <> 2006 ;
해당 식이 특정 범위 내에 있는지를 확인한다.
보통 숫자나 시간 데이터로 작업할 때 발생한다.
<=
, <
, >
, >=
등의 연산자로 범위를 지정할 수 있다.
2005-06-14
를 범위의 하한으로 지정하고, 2005-06-16
을 범위의 상한으로 지정하면 시간은 기본적으로 자정으로 설정된다.예를 들어, 영화같은 경우 관람등급이 나누어져 있다.
정해진 값의 범위가 있을 경우 동등조건 또는 IN
연산자를 사용할 수 있다.
예를 들어, 관람등급이 'G' 또는 'PG'인 영화만 보고싶을 경우 아래와 같은 쿼리로 해당 영화를 찾을 수 있다.
조건이 막 10개 이상으로 많아지게 되면 OR
을 사용하는게 오히려 비효율적일 수 있다.
이때 IN
을 사용한다.
SELECT title, rating
FROM film
WHERE rating='G'
OR rating='PG';
또는
SELECT title, rating
FROM film
WHERE rating
IN ('G', 'PG');
어떤 표현식이 "안 존재하는지" 여부를 확인하고 싶을 때 사용한다.
예를 들어, 'R', 'PG-13', 'NC-17' 등급이 아닌 영화를 찾고 싶다면
SELECT title, rating
FROM film
WHERE rating NOT IN ('R', 'PG-13', 'NC-17');
부분 문자열이 일치하는 데이터를 확인하고 싶을 때 사용한다. (예를 들면 'K'로 성이 시작하는 모든 사람을 검색하고 싶다거나)
_
: 글자숫자를 정해줌 (EX 컬럼명 LIKE '홍_동') , 정확히 1개 문자. %
: 글자숫자를 정해주지않음 (EX 컬럼명 LIKE '홍%') , 가변 문자. --A로 시작하는 문자를 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE 'A%'
--A로 끝나는 문자 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE '%A'
--A를 포함하는 문자 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE '%A%'
--A로 시작하는 두글자 문자 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE 'A_'
--첫번째 문자가 'A''가 아닌 모든 문자열 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE'[^A]'
--첫번째 문자가 'A'또는'B'또는'C'인 문자열 찾기--
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE '[ABC]'
SELECT 컬럼명 FROM 테이블 WHERE 컬럼명 LIKE '[A-C]'
last_name LIKE '_A_T%S'
→ 문자의 두번째 위치가 A이고, 네번째 위치가 T이고, 마지막이 S로 끝나는 성(lastName)을 찾을 것이다.
REGEXP
like
연산자와 함께 정규식을 사용할 수 있다.
성이 Q 또는 Y로 시작하는 고객을 찾고 싶을 때,
[방법1] LIKE 사용:
SELECT last_name, first_name
FROM customer
WHERE last_name LIKE 'Q%'
OR last_name LIKE 'Y%' ;
[방법2] 정규표현식(REGEXP) 사용:
SELECT last_name, first_name
FROM customer
WHERE last_name REGEXP '^[QY]' ;
null
일수는 있지만, null
과 같을 수는 없다.null
은 서로 같지 않다.값이 null
인 데이터를 확인하려면 IS NULL
을 사용하면 된다.
반대로 값이 열에 할당되었는지를 확인하려면 IS NOT NULL
을 사용한다.
한빛미디어의 'Learning SQL' 로 공부중인데, "4장 필터링" 마지막에 이상한 부분이 있어서 혼란스러웠다.
2005년 5월 ~ 8월 사이에 반납되지 않은 모든 DVD 대여정보를 찾고싶다고 가정했을 때, 아래 쿼리는 불완전하다고 지적했다.
불완전 :
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date NOT BETWEEN '2005-05-01' AND '2005-09-01' ;
----------
62 rows in set
왜냐하면 이렇게 쿼리를 작성하면 반납되지 않은 DVD가 아니고, 5~8월이 아닌 날짜에 "반납된" DVD 리스트가 보여질 것이기 때문이다.
따라서, null
이 포함된 아래와 같은 쿼리를 써야 한다고 나와있는데......
올바른 쿼리????? :
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date IS NULL
OR return_date NOT BETWEEN '2005-05-01' AND '2005-09-01' ;
----------
245 rows in set
이렇게 되면 5~8월이 아닌 날짜에 "반납된" DVD 리스트(62개)와, 아직 반납되지 않은 DVD리스트(183개)까지 함께 보여질 것이다.
따라서 원래 구하고 싶은 5~8월 사이에 반납되지 않은 DVD 정보는 아니라는거다.
왜냐하면 아직 반납되지 않은 DVD 리스트(183개)는 DVD가게를 처음 열었을 때부터 지금까지 반납되지 않은 모든 DVD일거기 때문이다.
만약 5~8월 사이 반납되지 않은 리스트를 구하고 싶다면
rental_date
와 film 테이블에서 rental_duration
을 이용해 "반납해야할 날짜"를 구한다음, return_date
가 NULL인 데이터를 찾아야하는게 맞지 않나... 왜냐면 return_date
는 반납해야할 날짜가 아니고, 실제로 고객이 반납한 날짜이기 때문이다.
따라서 2005년 5~8월 사이에 반납되지 않은 DVD 대여정보를 찾기에는 rental 테이블만으로는 어려워보인다.
암튼 필터링 끝 😊 이제 실습해보기로 한다.