비교 함수와 연산자
비교 함수와 연산자 (Comparison functions and operators)
이 문서는 Trino의 비교 함수와 연산자를 설명합니다. 값의 대소 비교, 범위 판단, null 처리, 패턴 매칭 등 다양한 비교 방식을 배울 수 있어요.
출처: 문서
본문
비교 연산자 (Comparison operators)
| 연산자 | 설명 |
|---|---|
> |
크다 (Greater than) |
>= |
크거나 같다 (Greater than or equal to) |
= |
같다 (Equal) |
<> |
같지 않다 (Not equal) |
!= |
같지 않다 (비표준이지만 널리 쓰이는 문법) |
범위 연산자: BETWEEN (Range operator: BETWEEN)
BETWEEN 연산자는 값이 지정된 범위 안에 있는지 검사합니다. 문법은 value BETWEEN min AND max입니다:
SELECT 3 BETWEEN 2 AND 6;
위 문장은 다음 문장과 동일합니다:
SELECT 3 >= 2 AND 3 <= 6;
값이 지정된 범위 안에 없는지 검사하려면 NOT BETWEEN을 사용하세요:
SELECT 3 NOT BETWEEN 2 AND 6;
위 문장은 다음 문장과 동일합니다:
SELECT 3 < 2 OR 3 > 6;
BETWEEN이나 NOT BETWEEN 문장의 NULL은 위 동등 표현식에 적용되는 표준 NULL 평가 규칙으로 평가됩니다:
SELECT NULL BETWEEN 2 AND 4; -- null
SELECT 2 BETWEEN NULL AND 6; -- null
SELECT 2 BETWEEN 3 AND NULL; -- false
SELECT 8 BETWEEN NULL AND 6; -- false
BETWEEN과 NOT BETWEEN 연산자는 정렬 가능한 모든 유형에도 사용할 수 있습니다. 예를 들어 VARCHAR:
SELECT 'Paul' BETWEEN 'John' AND 'Ringo'; -- true
BETWEEN과 NOT BETWEEN의 value, min, max 파라미터는 모두 같은 유형이어야 합니다. 예를 들어 Trino에 John이 2.3과 35.2 사이인지 물어보면 오류가 발생합니다.
대칭/비대칭 범위 (Symmetric and asymmetric ranges)
기본적으로 경계는 순서대로 해석되므로 value BETWEEN min AND max는 min <= max일 때만 일치합니다. 이 기본 동작은 ASYMMETRIC으로 명시할 수 있습니다:
SELECT 3 BETWEEN ASYMMETRIC 2 AND 6; -- true
SELECT 3 BETWEEN ASYMMETRIC 6 AND 2; -- false
SYMMETRIC를 사용하면 두 경계를 순서 없는 쌍으로 취급하므로, 값이 어느 순서든 두 경계 사이에 있으면 검사가 성공합니다. value BETWEEN SYMMETRIC min AND max는 value BETWEEN ASYMMETRIC min AND max OR value BETWEEN ASYMMETRIC max AND min과 동일합니다:
SELECT 3 BETWEEN SYMMETRIC 2 AND 6; -- true
SELECT 3 BETWEEN SYMMETRIC 6 AND 2; -- true
SYMMETRIC는 NOT과 결합할 수 있고, 동등하게 전개된 표현식과 같은 NULL 평가 규칙을 따릅니다.
IS NULL과 IS NOT NULL
IS NULL과 IS NOT NULL 연산자는 값이 null(정의되지 않음)인지 검사합니다. 두 연산자 모두 모든 데이터 유형에서 동작합니다.
NULL에 IS NULL을 사용하면 true로 평가됩니다:
SELECT NULL IS NULL; -- true
하지만 다른 상수는 그렇지 않습니다:
SELECT 3.0 IS NULL; -- false
IS TRUE, IS FALSE, IS UNKNOWN
IS [NOT] TRUE, IS [NOT] FALSE, IS [NOT] UNKNOWN 연산자는 부울 표현식의 3값 결과를 검사합니다. TRUE나 FALSE에 대한 직접 비교와 달리, 이 연산자는 항상 null이 아닌 부울을 반환하며 NULL(unknown) 피연산자를 알려진 값으로 취급합니다. 부울 피연산자에서 IS UNKNOWN은 IS NULL과 동일합니다:
SELECT (1 > 0) IS TRUE; -- true
SELECT (1 > 2) IS FALSE; -- true
SELECT (NULL > 0) IS UNKNOWN; -- true
SELECT (NULL > 0) IS NOT TRUE; -- true
다음 진리표는 각 진리값의 처리를 보여줍니다:
| a | a IS TRUE | a IS FALSE | a IS UNKNOWN | a IS NOT TRUE | a IS NOT FALSE | a IS NOT UNKNOWN |
|---|---|---|---|---|---|---|
TRUE |
TRUE |
FALSE |
FALSE |
FALSE |
TRUE |
TRUE |
FALSE |
FALSE |
TRUE |
FALSE |
TRUE |
FALSE |
TRUE |
NULL |
FALSE |
FALSE |
TRUE |
TRUE |
TRUE |
FALSE |
IS DISTINCT FROM과 IS NOT DISTINCT FROM
SQL에서 NULL 값은 알 수 없는 값을 의미하므로 NULL이 포함된 어떤 비교도 NULL을 생성합니다. IS DISTINCT FROM과 IS NOT DISTINCT FROM 연산자는 NULL을 알려진 값으로 취급하며, NULL 입력이 있어도 두 연산자 모두 true 또는 false 결과를 보장합니다:
SELECT NULL IS DISTINCT FROM NULL; -- false
SELECT NULL IS NOT DISTINCT FROM NULL; -- true
위 예제에서 NULL 값은 NULL과 구별되지 않는 것으로 간주됩니다. NULL을 포함할 수 있는 값을 비교할 때는 이 연산자를 사용해 TRUE 또는 FALSE 결과를 보장하세요.
다음 진리표는 IS DISTINCT FROM과 IS NOT DISTINCT FROM에서의 NULL 처리를 보여줍니다:
| a | b | a = b | a <> b | a DISTINCT b | a NOT DISTINCT b |
|---|---|---|---|---|---|
1 |
1 |
TRUE |
FALSE |
FALSE |
TRUE |
1 |
2 |
FALSE |
TRUE |
TRUE |
FALSE |
1 |
NULL |
NULL |
NULL |
TRUE |
FALSE |
NULL |
NULL |
NULL |
NULL |
FALSE |
TRUE |
GREATEST와 LEAST
이 함수들은 SQL 표준에 없지만 흔한 확장입니다. Trino의 다른 대부분의 함수처럼, 어떤 인수가 null이면 null을 반환합니다. PostgreSQL 같은 일부 다른 데이터베이스에서는 모든 인수가 null일 때만 null을 반환한다는 점에 유의하세요.
다음 유형이 지원됩니다: DOUBLE, BIGINT, VARCHAR, TIMESTAMP, TIMESTAMP WITH TIME ZONE, DATE.
greatest(value1, value2, ..., valueN) → [입력과 동일]
제공된 값 중 가장 큰 값을 반환합니다.
least(value1, value2, ..., valueN) → [입력과 동일]
제공된 값 중 가장 작은 값을 반환합니다.
양화 비교 조건: ALL, ANY, SOME (Quantified comparison predicates)
ALL, ANY, SOME 양화사는 비교 연산자와 함께 다음 방식으로 사용할 수 있습니다:
expression operator quantifier ( subquery )
예를 들어:
SELECT 'hello' = ANY (VALUES 'hello', 'world'); -- true
SELECT 21 < ALL (VALUES 19, 20, 21); -- false
SELECT 42 >= SOME (SELECT 41 UNION ALL SELECT 42 UNION ALL SELECT 43); -- true
다음은 일부 양화사와 비교 연산자 조합의 의미입니다:
| 표현식 | 의미 |
|---|---|
A = ALL (...) |
A가 모든 값과 같으면 true로 평가. |
A <> ALL (...) |
A가 어떤 값과도 일치하지 않으면 true로 평가. |
A >= ANY (...) |
A가 하나 이상의 값과 일치하면 true로 평가. |
A < SOME (...) |
A가 하나 이상의 값보다 작으면 true로 평가. |
패턴 비교: LIKE (Pattern comparison: LIKE)
LIKE 연산자는 값을 패턴과 비교할 때 사용할 수 있습니다:
... column [NOT] LIKE 'pattern' ESCAPE 'character';
문자 일치는 대소문자를 구분하며, 패턴은 매칭에 두 가지 기호를 지원합니다:
_는 임의의 단일 문자와 일치%는 0개 이상의 문자와 일치
보통 WHERE 문의 조건으로 자주 사용됩니다. 예를 들어 E로 시작하는 모든 대륙(Europe을 반환)을 찾는 쿼리:
SELECT * FROM (VALUES 'America', 'Asia', 'Africa', 'Europe', 'Australia', 'Antarctica') AS t (continent)
WHERE continent LIKE 'E%';
NOT을 추가해 결과를 부정하면 E로 시작하지 않는 모든 다른 대륙을 얻을 수 있습니다:
SELECT * FROM (VALUES 'America', 'Asia', 'Africa', 'Europe', 'Australia', 'Antarctica') AS t (continent)
WHERE continent NOT LIKE 'E%';
일치시킬 특정 문자가 하나뿐이면 각 문자에 _ 기호를 사용할 수 있습니다. 다음 쿼리는 밑줄 두 개를 사용해 Asia만 결과로 만듭니다:
SELECT * FROM (VALUES 'America', 'Asia', 'Africa', 'Europe', 'Australia', 'Antarctica') AS t (continent)
WHERE continent LIKE 'A__a';
와일드카드 문자 _와 %를 리터럴로 일치시키려면 이스케이프해야 합니다. 사용할 ESCAPE 문자를 지정하면 됩니다:
SELECT 'South_America' LIKE 'South\_America' ESCAPE '\';
위 쿼리는 이스케이프된 밑줄 기호가 일치하므로 true를 반환합니다. 사용된 이스케이프 문자 자체를 일치시켜야 한다면 그 문자도 이스케이프할 수 있습니다. 예를 들어 \\를 사용해 \를 일치시킬 수 있습니다.
행 비교: IN (Row comparison: IN)
IN 연산자는 WHERE 절에서 컬럼 값을 값 목록과 비교할 때 사용할 수 있습니다. 값 목록은 서브쿼리로 제공하거나 배열의 정적 값으로 직접 제공할 수 있습니다:
... WHERE column [NOT] IN ('value1','value2');
... WHERE column [NOT] IN ( subquery );
선택적 NOT 키워드로 조건을 부정할 수 있습니다.
다음 예제는 정적 배열과의 간단한 사용입니다:
SELECT * FROM region WHERE name IN ('AMERICA', 'EUROPE');
절의 값들은 논리 OR로 결합된 여러 비교에 사용됩니다. 위 쿼리는 다음 쿼리와 동일합니다:
SELECT * FROM region WHERE name = 'AMERICA' OR name = 'EUROPE';
NOT을 추가하면 비교를 부정해 목록의 값들을 제외한 모든 다른 지역을 얻을 수 있습니다:
SELECT * FROM region WHERE name NOT IN ('AMERICA', 'EUROPE');
서브쿼리를 사용해 비교에 사용할 값을 결정할 때, 서브쿼리는 단일 컬럼과 하나 이상의 행을 반환해야 합니다. 예를 들어 다음 쿼리는 A로 시작하는 지역(특히 Africa, America, Asia)의 국가 이름을 반환합니다:
SELECT nation.name
FROM nation
WHERE regionkey IN (
SELECT regionkey
FROM region
WHERE starts_with(name, 'A')
)
ORDER by nation.name;
행 매칭: MATCH (Row matching: MATCH)
MATCH 조건은 행 값이 서브쿼리가 반환한 행과 일치하는지 검사합니다:
row MATCH [UNIQUE] [SIMPLE | PARTIAL | FULL] ( subquery )
왼쪽은 행 값이고 서브쿼리는 같은 차수의 행을 반환해야 합니다. 선택적 매치 유형은 행의 NULL 처리 방식을 제어하며 기본값은 SIMPLE입니다.
SELECT ROW(1, 'a') MATCH (VALUES (1, 'a'), (2, 'b')); -- true
SELECT ROW(99, 'z') MATCH (VALUES (1, 'a'), (2, 'b')); -- false
전형적인 용도는 한 관계의 행 중 다른 관계에도 있는 행을 유지하는 것입니다. 서브쿼리는 바깥 쿼리와 상관될 수 있습니다:
SELECT a
FROM (VALUES (1, 'a'), (2, 'b'), (3, 'c')) t(a, b)
WHERE ROW(a, b) MATCH (VALUES (1, 'a'), (3, 'c')); -- returns 1 and 3
매치 유형 (Match types)
매치 유형은 왼쪽의 행이 NULL을 포함할 때의 결과를 결정합니다:
| 매치 유형 | 행의 NULL 필드 처리 |
|---|---|
SIMPLE |
기본값. NULL을 포함하는 행은 서브쿼리 내용과 무관하게 항상 일치. |
PARTIAL |
NULL 필드는 그 위치의 어떤 값과도 일치하는 와일드카드이며, null이 아닌 필드는 서브쿼리 행의 값과 같아야 합니다. 모든 필드가 NULL인 행은 항상 일치. |
FULL |
행이 NULL을 포함하지 않고 서브쿼리 행과 같을 때만 일치하거나, 모든 필드가 NULL일 때 일치. NULL과 null이 아닌 필드가 섞인 행은 절대 일치하지 않음. |
다음 예제는 첫 필드가 NULL인 행으로 매치 유형들의 차이를 보여줍니다:
SELECT ROW(NULL, 'a') MATCH SIMPLE (VALUES (1, 'z')); -- true
SELECT ROW(NULL, 'a') MATCH PARTIAL (VALUES (1, 'a')); -- true
SELECT ROW(NULL, 'a') MATCH PARTIAL (VALUES (1, 'z')); -- false
SELECT ROW(NULL, 'a') MATCH FULL (VALUES (1, 'a')); -- false
고유 매치 (Unique matches)
행이 서브쿼리의 정확히 한 행과 일치하도록 요구하려면 UNIQUE 키워드를 추가하세요. 일치하는 행이 두 번 이상 나타나면 결과는 false입니다. UNIQUE는 어떤 매치 유형과도 결합할 수 있습니다. 예: MATCH UNIQUE PARTIAL:
SELECT ROW(1, 'a') MATCH UNIQUE (VALUES (1, 'a')); -- true
SELECT ROW(1, 'a') MATCH UNIQUE (VALUES (1, 'a'), (1, 'a')); -- false
고유성 검사: UNIQUE (Uniqueness test: UNIQUE)
UNIQUE 조건은 서브쿼리가 중복 행을 포함하는지 검사합니다. 서브쿼리의 두 행이 서로 같지 않으면 true, 그렇지 않으면 false를 반환합니다:
UNIQUE ( subquery )
SELECT UNIQUE (VALUES 1, 2, 3); -- true
SELECT UNIQUE (VALUES 1, 1, 2); -- false
어떤 컬럼에 NULL을 포함하는 행은 동일한 행과도 절대 중복으로 세지 않습니다. 모든 컬럼이 null이 아닌 행만이 중복 쌍을 이룰 수 있습니다:
-- 두 행은 동일하지만 각각 NULL을 포함하므로 중복이 아님
SELECT UNIQUE (VALUES (CAST(NULL AS integer), 'a'), (CAST(NULL AS integer), 'a')); -- true
-- (1, 'b') 쌍은 중복; NULL 행은 관련 없음
SELECT UNIQUE (VALUES (CAST(NULL AS integer), 'a'), (1, 'b'), (1, 'b')); -- false
결과적으로 빈 서브쿼리와 모든 행이 NULL을 포함하는 서브쿼리 모두 UNIQUE를 만족합니다:
SELECT UNIQUE (SELECT 1 WHERE false); -- true
NOT을 사용해 중복 존재를 검사할 수 있습니다:
SELECT NOT UNIQUE (VALUES 1, 1); -- true
UNIQUE 조건의 서브쿼리는 바깥 쿼리와 상관될 수 없습니다.
예제 (Examples)
다음 예제 쿼리는 값의 암시적 순서, 암시적 캐스팅, 서로 다른 유형과 관련된 비교 함수/연산자 사용의 측면을 보여줍니다.
순서 (Ordering):
SELECT 'M' BETWEEN 'A' AND 'Z'; -- true
SELECT 'A' < 'B'; -- true
SELECT 'A' < 'a'; -- true
SELECT TRUE > FALSE; -- true
SELECT 'M' BETWEEN 'A' AND 'Z'; -- true
SELECT 'm' BETWEEN 'A' AND 'Z'; -- false
다음 쿼리는 char와 varchar 유형의 미묘한 차이를 보여줍니다. varchar의 길이 파라미터는 선택적 최대 길이 파라미터이며, 비교는 길이를 무시하고 데이터만 기반으로 합니다:
SELECT cast('Test' as varchar(20)) = cast('Test' as varchar(25)); --true
SELECT cast('Test' as varchar(20)) = cast('Test ' as varchar(25)); --false
char의 길이 파라미터는 고정 길이 문자 배열을 정의합니다. 길이가 다른 비교는 자동으로 더 큰 길이로 캐스팅합니다. 캐스팅은 공백으로 자동 패딩하므로 다음 두 쿼리 모두 true를 반환합니다:
SELECT cast('Test' as char(20)) = cast('Test' as char(25)); -- true
SELECT cast('Test' as char(20)) = cast('Test ' as char(25)); -- true
다음 쿼리는 date 유형이 어떻게 정렬되는지, 그리고 date가 zero time 값을 가진 timestamp로 어떻게 암시적 캐스팅되는지 보여줍니다:
SELECT DATE '2024-08-22' < DATE '2024-08-31';
SELECT DATE '2024-08-22' < TIMESTAMP '2024-08-22 8:00:00';
더 알아보기 (Learn more)
다른 함수 주제도 살펴보세요. 조건부 표현식, 문자열 함수, 날짜/시간 함수 등 각 주제별 문서에서 더 많은 기능을 배울 수 있어요.