Special WHERE operators - 특별한 WHERE 연산자
당신은 이미 복잡한 SQL 쿼리들과 논리 표현식을 작성 할 줄 압니다.
이번 주제에서는, 우리는 특별한 WHERE 연산자들을 더 보게 될 겁니다.
BETWEEN,IN,LIKE,EXISTS,ANY,IS NULLandIS DISTINCT FROM
위의 단어들은 당신의 쿼리들을 더 발전되고 가독성 있게 만듭니다.
BETWEEN operator - BETWEEN 연산자
WHERE 절 내부의 BETWEEN 연산자는 주어진 영역의 값들을 선택합니다.
주어진 영역은 최소와 최대 값의 집합인데, 이는 날짜, 숫자, 텍스트 데이터를 담을 수 있습니다.
BETWEEN 연산자는 포괄적인데, 이는 최소값과 최대값들이 영역 내부에 포함되게 합니다.
함께 제품들을 선택해 보는데, 가격이 8 과 같거나 크고, 13보다 작거나 같은 것을 고릅니다.
한 번 주어진 products 테이블에서 골라보죠!
| product | price |
|---|---|
| milk | 10 |
| tofu | 15 |
| pasta | 12 |
| bread | 8 |
WHERE BETWEEN 을 사용한 쿼리는 밑의 예제와 같습니다 :
SELECT
product
FROM
products
WHERE
price BETWEEN 8 AND 13;
위의 쿼리의 결과 집합은 세 개의 줄을 가집니다.
| product |
|---|
| milk |
| pasta |
| bread |
BETWEEN을 제외한 쿼리도 같은 결과 집합을 얻을 수 있습니다.
SELECT
product
FROM
products
WHERE
(price >= 8
AND price <= 13);
위의 쿼리를 본다면, WHERE BETWEEN 연산자가
WHERE 절에서의 >= AND <= 표현에 대한 단축어라는 것을 생각할 수 있습니다.
바깥 영역의 모든 제품을 선택하기 위해 NOT BETWEEN 연산자를 사용 할 수 있습니다.
SELECT
product
FROM
products
WHERE
price NOT BETWEEN 8 AND 13;
결과 집합은 원래 나왔던 세 개의 줄을 제외하고 있습니다. :
| product |
|---|
| tofu |
IN operator - IN 연산자
WHERE 절에서의 IN 연산자는 다중 OR 조건절의 단축어이기도 하며, 여러 개의 값을 표기하기 허용합니다.
이전 예제의 products 테이블로부터 10, 12, 16 가격과 같은 제품들을 선택 해 봅시다.
SELECT
product
FROM
products
WHERE
price IN (10, 12, 16);
이 쿼리의 결과는 밑과 같습니다. :
| product |
|---|
| milk |
| pasta |
10, 12, 16과 다른 가격의 제품들을 선택하기 위해서
NOT을 사용하여 IN 연산자를 부정 할 수 있습니다.
SELECT
product
FROM
products
WHERE
price NOT IN (10, 12, 16);
이 쿼리를 사용하면, milk, pasta를 제외한 모든 제품을 가져옵니다.
| product |
|---|
| tofu |
| bread |
LIKE operator - Like 연산자
LIKE 연산자는 WHERE 절에서 쓰일 수 있는데, 문자열이 패턴과 맞는지 확인하기 위해서 쓰입니다.
패턴을 만들기 위해 두 개의 wildcard match options 를 사용할 수 있습니다. : % and _.
% 는 모든 숫자, 혹은 문자를 표현합니다. : 0, 1, ...
예를 들어, 패턴을 %s%로 쓴다면,
문자열 s, toaster, string, cats 문자열이 이 패턴과 일치합니다.
_는 정확히 하나의 문자를 표현합니다.
따라서, 패턴을 s_로 작성한다면, 문자열 so 가 이 패텬과 일치합니다.
문자열 s, soap는 일치하지 않습니다.
함께 products 테이블로부터 'a' 문자열이 들어간 모든 제품들을 선택해 보겠습니다.
SELECT
product
FROM
products
WHERE
product LIKE '%a%';
쿼리는 이러한 테이블을 반환합니다 :
| product |
|---|
| pasta |
| bread |
BETWEEN과 IN 연산자처럼,
a 문자열이 들어가지 않은 제품 이름을 얻기 위해 NOT과 LIKE 연산자로 부정할 수 있습니다.
SELECT
product
FROM
products
WHERE
product NOT LIKE '%a%';
EXISTS operator
EXISTS 연산자는 서브쿼리가 어떠한 레코드라도 반환하는지 아닌지 체크합니다.
만약 서브쿼리가 어떠한 레코드라도 반환한다면, EXISTS 연산자는 TRUE를 반환합니다.
그 반대라면,(어떠한 레코드도 반환되지 않음) FALSE를 반환합니다.
suppliers 테이블을 봅시다. :
| supplier | product |
|---|---|
| Good food | pasta |
| Happy farm | milk |
| Good food | milk |
| Happy farm | bread |
| Good food | cheese |
우리는 EXISTS 연산자를 사용하여 milk와 pasta 둘 다 공급하는 공급자들을 모두 선택합니다. :
SELECT DISTINCT
supplier
FROM suppliers AS milk_suppliers
WHERE
product = 'milk'
AND EXISTS
(SELECT supplier
FROM
suppliers
WHERE
product = 'pasta'
AND supplier = milk_suppliers.suppliers
);
이 경우, 쿼리의 결과는 밑과 같습니다 :
| supplier |
|---|
| Good food |
부정 EXISTS 연산자는 서브쿼리가 어떠한 레코드라도 반환한다면 FALSE를 반환합니다.
그 반대의 경우 (어떤 레코드도 반환하지 않은 상황) , TRUE를 반환합니다.
우리는 이전 쿼리를 수정하여 milk는 공급하지만, pasta는 공급하지 않는 공급자를 선택 할 수 있습니다.
SELECT DISTINCT
supplier
FROM
suppliers AS milk_suppliers
WHERE
product = 'milk'
AND NOT EXISTS
(SELECT
supplier
FROM
suppliers
WHERE
product = 'pasta'
AND suppliers = milk_suppliers
);
이 쿼리는 이 테이블을 반환합니다 :
| milk_suppliers |
|---|
| Happy farm |
products :
| product | price |
|---|---|
| milk | 10 |
| tofu | 15 |
| pasta | 12 |
| bread | 8 |
suppliers :
| supplier | product |
|---|---|
| Good food | pasta |
| Happy farm | milk |
| Good food | milk |
| Happy farm | bread |
| Good food | cheese |
ANY operator - ANY 연산자
ANY 연산자는 서브쿼리가 어떠한 조건이라도 충족한다면, TRUE를 반환합니다.
products, suppliers 테이블을 사용하고,
ANY 연산자를 사용하여 products 테이블 내부 목록에 없는 제품을 공급하는 공급자를 찾습니다.
supplier 중에서,
products테이블에 없는 제품을 파는 사람을 찾는다! 라는 의미이다.
SELECT DISTINCT
supplier
FROM
suppliers
WHERE
NOT product = ANY (SELECT product FROM products);
쿼리의 결과는 밑과 같습니다 :
| supplier |
|---|
| Good food |
ANY 연산자는 표준 비교 연산자 이후에만 사용 할 수 있습니다.
ex - =, !=, <=, 등등...
supplier과product가 같은 줄에 존재한다.
product 값을products테이블의 product 값과 비교한다.ANY를 통해 선택된 product 값이 반환되는데,product: suppliers =product: products
와 같은 형태가 된다.
이 때,NOT이 존재하기 때문에,suppliers.product.!=products.product.all()과 같은
형태가 된다. - 이는 실존하는 코드가 아니라, 이해를 위한 코드.
따라서,NOT으로 인해products목록에 존재하지 않는 제품을 파는suppliers를 찾는다.
나도 헷갈려서 짚고 넘어가기
1. EXISTS
서브쿼리로 작성된 코드가 하나라도 레코드를 내뱉는다면, TRUE로 환산된다.
그 외의 경우, FALSE로 환산된다.
반환값 : boolean
2. ANY
서브쿼리로 작성된 코드가 모든 products 값을 반환한다.
이 때, supplier에서 선택된 제품과 모든 products 값을 비교합니다.
Hyperskill 문서에서는 TRUE, FALSE 로 치환된다고 설명하는데,
실제로는 비교식을 위해 값이 반환된다고 생각하면 됩니다.
suppliers.product와 products.All()을 비교한다고 해석하면 됩니다.
IS NULL operator - IS NULL 연산자
IS NULL 연산자는 컬럼의 값이 NULL과 일치한다면 TRUE를 반환합니다.
밑의 persons 테이블을 보겠습니다. :
| name | city |
|---|---|
| John Oh | New-York |
| Eve Comer | NULL |
| Kim Wilson | London |
persons 테이블로부터 도시에 대한 정보가 없는 모든 줄을 선택하기 위해 IS NULL 연산자를 사용 할 수 있습니다.
SELECT
name
FROM
persons
WHERE
city IS NULL;
쿼리 결과는 밑과 같습니다. :
| name |
|---|
| Eve Comer |
도시에 대한 정보가 NULL 이 아닌 모든 줄을 선택하기 위해 IS NOT NULL 연산자를 사용 할 수 있습니다.
SELECT
name
FROM
persons
WHERE
city IS NOT NULL;
IS DISTINCT FROM operator - IS DISTINCT FROM 연산자
평범한 비교 연산자들은 TRUE 혹은 FALSE를 반환하는데, 이것이 아니면 NULL을 반환합니다.
이 결과를 원하지 않을 때, IS DISTINCT FROM 연산자가 쓰입니다.
IS DISTINCT FROM 연산자는 !=, <> 와 매우 유사합니다.
이 연산자는 두 값이 서로 다르다면 TRUE를 반환하며, 그 반대의 경우 FALSE를 반환합니다.
만약 양 측의 값이 NULL이라면, IS DISTINCT FROM 연산자는 TRUE를 반환합니다.
이 연산자는 표준 비균등 체킹 연산자와 구별되는 점 입니다.
비균등 체킹 연산자 -
!=,<>...
다른 의미로, 이 구성은 본질적으로 NULL을 일반 값처럼 작업하며,
UNKNOWN 대신 TRUE 또는 FALSE를 반환합니다.
NULL = NULL => UNKNOWN
NULL IS NOT DISTINCT FROM NULL => TRUE
persons 테이블로부터 New-York 도시 값과 같지 않는 모든 줄을 선택합니다.
SELECT
*
FROM
persons
WHERE
city IS DISTINCT FROM 'New-York';
위의 쿼리는 두 개의 줄을 선택합니다. :
| name | city |
|---|---|
| Eve Comer | NULL |
| Kim Wilson | London |
이 연산자를 부정하는 IS NOT DISTINCT FROM 연산자는 null을 다루지 않는 균등 체킹 연산자처럼 작동합니다.
그리고 양 쪽 값이 모두 NULL 이라면, TRUE 를 반환합니다.
양 쪽 값을 비교할 때, 마치 객체 비교처럼 작동하는 것으로 이해했다.
persons 테이블에서 도시 값이 NULL과 같은 모든 줄을 선택합니다.
SELECT
*
FROM
persons
WHERE
city IS NOT DISTINCT FROM NULL;
이 쿼리는 이 줄을 반환합니다.
| name | city |
|---|---|
| Eve Comer | NULL |
Conclusion - 결론
특별한 연산자인 WHERE 은 쿼리들을 더 간단하고, 더 발전된 서브쿼리를 만들 수 있게 해 줍니다.
연습합시다!
'Hyperskill - 컴퓨터 CS 및 영어 독해 > Introducing to SQL' 카테고리의 다른 글
| Basic DELETE statement - 기초적인 DELETE 문법 (0) | 2024.04.16 |
|---|---|
| Basic INSERT statement - 기초적인 INSERT 문법 (0) | 2024.04.15 |
| The NULL value - null 값 (0) | 2024.04.13 |
| Logic and comparison expressions - 로직, 비교 표현식 (1) | 2024.04.12 |
| SELECT FROM statement - SELECT FROM 구문 (0) | 2024.04.10 |