연산자

연산자 (Operators)

ClickHouse는 쿼리 파싱 단계에서 연산자를 우선순위, 결합 방향에 따라 대응하는 함수로 변환해요. 이 페이지는 접근·산술·비교·논리 연산자와 날짜·시간, 문자열, 데이터 집합 작업용 연산자를 정리한 참조자료입니다.

출처: 문서

본문

ClickHouse는 쿼리 파싱 단계에서 연산자를 우선순위·전위·결합성에 따라 대응하는 함수로 변환합니다.

Access Operators

a[N] – 배열의 요소에 접근. arrayElement(a, N) 함수. N은 정수 배열일 수도 있는데, 이 경우 그 모든 위치의 요소가 배열로 반환되며 arrayMap(i -> a[i], N)과 같아요. 위치는 nullable일 수 있어요. NULL 위치는 요소 타입을 Nullable로 감쌀 수 있으면 NULL을 만들고, Nullable 안에 넣을 수 없는 요소 타입(예: Array, Map)의 경우 스칼라 NULL 인덱스와 마찬가지로 요소 타입의 기본값을 만듭니다. a.N – 튜플 요소에 접근. tupleElement(a, N) 함수.

Numeric Negation Operator

-anegate (a) 함수. 튜플 부정에 대해서는 tupleNegate를 참고하세요.

Multiplication and Division Operators

a * bmultiply (a, b) 함수. 튜플에 숫자 곱셈: tupleMultiplyByNumber, 스칼라 곱: dotProduct. a / bdivide(a, b) 함수. 튜플을 숫자로 나누기: tupleDivideByNumber. a % bmodulo(a, b) 함수.

Addition and Subtraction Operators

a + bplus(a, b) 함수. 튜플 덧셈: tuplePlus. a - bminus(a, b) 함수. 튜플 뺄셈: tupleMinus.

Comparison Operators

equals function

a = bequals(a, b) 함수.a == bequals(a, b) 함수.

notEquals function

a != bnotEquals(a, b) 함수.a <> bnotEquals(a, b) 함수.

lessOrEquals function

a <= blessOrEquals(a, b) 함수.

greaterOrEquals function

a >= bgreaterOrEquals(a, b) 함수.

less function

a < bless(a, b) 함수.

greater function

a > bgreater(a, b) 함수.

like function

a LIKE blike(a, b) 함수.

notLike function

a NOT LIKE bnotLike(a, b) 함수.

ilike function

a ILIKE bilike(a, b) 함수.

match function

a REGEXP bmatch(a, b) 함수.a ~ bmatch(a, b) 함수(PostgreSQL 스타일 정규 표현식 매칭).

notMatch function

a !~ bnotMatch(a, b) 함수(a가 정규 표현식 b와 일치하지 않는지 확인).

matchCaseInsensitive function

a ~* bmatchCaseInsensitive(a, b) 함수(대소문자 무시 정규 표현식 매칭).

notMatchCaseInsensitive function

a !~* bnotMatchCaseInsensitive(a, b) 함수(a가 정규 표현식 b와 대소문자 무시로 일치하지 않는지 확인).

BETWEEN function

a BETWEEN b AND ca >= b AND a <= c와 같음.a NOT BETWEEN b AND ca < b OR a > c와 같음.

is not distinct from operator ( <=> )

버전 25.10부터 <=>를 다른 연산자와 같은 방식으로 사용할 수 있어요. 25.10 이전에는 JOIN 표현식에서만 사용할 수 있었습니다. 예를 들면:

CREATE TABLE a (x String) ENGINE = Memory;
INSERT INTO a VALUES ('ClickHouse');

SELECT * FROM a AS a1 JOIN a AS a2 ON a1.x <=> a2.x;

┌─x──────────┬─a2.x───────┐
│ ClickHouse │ ClickHouse │
└────────────┴────────────┘

<=> 연산자는 IS NOT DISTINCT FROM과 동등한 NULL 안전 동등 연산자예요. 일반 동등 연산자(=)처럼 동작하지만, NULL 값을 비교 가능한 것으로 취급합니다. 두 NULL 값은 같다고 간주되며, NULLNULL이 아닌 값과 비교하면 NULL이 아니라 0(false)을 반환해요.

SELECT
  'ClickHouse' <=> NULL,
  NULL <=> NULL
┌─isNotDistinc⋯use', NULL)─┬─isNotDistinc⋯NULL, NULL)─┐
│                        0 │                        1 │
└──────────────────────────┴──────────────────────────┘

Operators for Working with Strings

OVERLAY

  • OVERLAY(string PLACING replacement FROM offset) - overlay(string, replacement, offset) 함수.
  • OVERLAY(string PLACING replacement FROM offset FOR length) - overlay(string, replacement, offset, length) 함수.
  • OVERLAYUTF8(string PLACING replacement FROM offset) - overlayUTF8(string, replacement, offset) 함수.
  • OVERLAYUTF8(string PLACING replacement FROM offset FOR length) - overlayUTF8(string, replacement, offset, length) 함수.

Operators for Working with Data Sets

IN 연산자EXISTS 연산자를 참고하세요.

in function

a IN ...in(a, b) 함수.

notIn function

a NOT IN ...notIn(a, b) 함수.

globalIn function

a GLOBAL IN ...globalIn(a, b) 함수.

globalNotIn function

a GLOBAL NOT IN ...globalNotIn(a, b) 함수.

in subquery function

a = ANY (subquery)in(a, subquery) 함수.

notIn subquery function

a != ANY (subquery)a NOT IN (SELECT singleValueOrNull(*) FROM subquery)와 같음.

in subquery function

a = ALL (subquery)a IN (SELECT singleValueOrNull(*) FROM subquery)와 같음.

notIn subquery function

a != ALL (subquery)notIn(a, subquery) 함수. Examples ALL이 있는 쿼리: Query

SELECT number AS a FROM numbers(10) WHERE a > ALL (SELECT number FROM numbers(3, 3));

Response

┌─a─┐
│ 6 │
│ 7 │
│ 8 │
│ 9 │
└───┘

ANY가 있는 쿼리: Query

SELECT number AS a FROM numbers(10) WHERE a > ANY (SELECT number FROM numbers(3, 3));

Response

┌─a─┐
│ 4 │
│ 5 │
│ 6 │
│ 7 │
│ 8 │
│ 9 │
└───┘

SOME / ALL on arrays

위에서 설명한 서브쿼리 형태 외에도, SOME / ALL의 오른쪽은 배열 표현식(배열 리터럴, 배열 타입 열, 배열을 반환하는 어떤 표현식)일 수 있어요. 이는 PostgreSQL 스타일의 배열 양화사 문법입니다. 파싱 시점에 인식되어 배열 함수로 다시 쓰여지므로 수동으로 다시 쓸 필요가 없습니다:

Syntax Rewritten to
expr = SOME(arr) has(arr, expr)
expr <> ALL(arr) NOT has(arr, expr)
expr OP SOME(arr) (any other supported operator) arrayExists(x -> expr OP x, arr)
expr OP ALL(arr) (any other supported operator) arrayAll(x -> expr OP x, arr)

SOME은 존재 양화사입니다(ANY의 SQL 동의어). =<>는 최적화된 구현이 있으므로 has / NOT has로 특별히 처리되며, 일반 형태는 고차 함수 arrayExists / arrayAll로 폴백합니다. 배열 형태는 비교 연산자 =, ==, !=, <>, <=>, <, <=, >, >=, 키워드 비교 술어 IS DISTINCT FROMIS NOT DISTINCT FROM, 그리고 문자열 검색 술어 LIKE, ILIKE, NOT LIKE, NOT ILIKE, REGEXP에 대해 인식됩니다. 키워드 비교 술어와 문자열 검색 술어는 서브쿼리 형태(IN/NOT IN으로 낮춰짐)가 아니라 배열 형태에서만 인식됩니다. 배열 양화사 의미가 없는 연산자 — 예를 들어 IN 자체 — 는 다시 쓰이지 않고 일반적인 의미를 유지합니다. 문자열 검색 술어는 MatchImpl(LIKE / ILIKE / REGEXP 뒤의 구현)이 상수 haystack과 상수가 아닌 needle을 지원하기 때문에 동작합니다. 예를 들어 'abc' LIKE SOME(['a%', 'b%'])arrayExists(x -> 'abc' LIKE x, ['a%', 'b%'])로, 'abc' NOT LIKE ALL(['x%', 'y%'])arrayAll(x -> 'abc' NOT LIKE x, ['x%', 'y%'])로 다시 쓰여집니다. 이는 하나의 문자열을 여러 패턴과 매칭하며, 단일 결합 패스로 매칭하려면 multiMatchAny(정규 표현식)나 multiSearchAny(부분 문자열) 같은 다중 패턴 검색 함수를 사용할 수 있어요. ANY는 배열 형태에서 지원되지 않습니다 배열 오른쪽을 받는 것은 SOMEALL뿐이에요. ANYany가 집계 함수이기도 하므로 제외됩니다. expr = any(x) 형태의 표현식은 함수 호출 의미를 유지합니다. 배열 양화사에는 SOME을 사용하세요. Query

SELECT
    3 = SOME([1, 2, 3, 4])         AS in_array,
    5 < SOME([1, 2, 6])            AS less_than_some,
    5 > ALL([1, 2, 3])             AS greater_than_all,
    'abc' LIKE SOME(['a%', 'z%'])  AS like_some;

Response

┌─in_array─┬─less_than_some─┬─greater_than_all─┬─like_some─┐
│        1 │              1 │                1 │         1 │
└──────────┴────────────────┴──────────────────┴───────────┘

NULL 처리 방식이 서브쿼리 형태와 다릅니다 배열 형태는 파서에서 다시 쓰여지므로(쿼리 설정인 transform_null_in을 사용할 수 없고, 행별 배열 열은 분석기의 null-safe IN 경로를 사용할 수 없음), =/<>에 대해 has의, 그리고 알 수 없는 NULL 비교 결과를 0으로 접는 arrayExists/arrayAll의 이중 값 시맨틱을 사용해요. 이는 NULL 처리가 IN/NOT IN을 통해 낮춰지고 transform_null_in에 의존하는 서브쿼리 형태와 다를 수 있습니다:

SELECT NULL = SOME([NULL]);   -- has([NULL], NULL)                  -> 1
SELECT NULL <> ALL([NULL]);   -- NOT has([NULL], NULL)              -> 0
SELECT NULL < SOME([1]);      -- arrayExists(x -> NULL < x, [1])    -> 0
SELECT NULL > ALL([1]);       -- arrayAll(x -> NULL > x, [1])       -> 0

Operators for Working with Dates and Times

EXTRACT

EXTRACT(part FROM date);

주어진 날짜에서 부분을 추출해요. 예를 들어 주어진 날짜에서 월을, 또는 시간에서 초를 가져올 수 있어요. part 매개변수는 날짜의 어느 부분을 가져올지 지정합니다. 다음 값들을 사용할 수 있어요:

  • NANOSECOND — 나노초. 가능한 값: 0–999999999.
  • MICROSECOND — 마이크로초. 가능한 값: 0–999999.
  • MILLISECOND — 밀리초. 가능한 값: 0–999.
  • SECOND — 초. 가능한 값: 0–59.
  • MINUTE — 분. 가능한 값: 0–59.
  • HOUR — 시. 가능한 값: 0–23.
  • DAY — 월의 일. 가능한 값: 1–31.
  • WEEK — ISO 8601 주 번호. 가능한 값: 1–53.
  • MONTH — 월 번호. 가능한 값: 1–12.
  • QUARTER — 분기. 가능한 값: 1–4.
  • YEAR — 연도.
  • EPOCH — Unix 타임스탬프(1970-01-01 00:00:00 UTC 이후 초). 참고: DateTime64 의 경우 초 미만 부분은 잘립니다.
  • DOW — 주의 요일(PostgreSQL 호환). 0 = 일요일, 6 = 토요일.
  • DOY — 연중 일수. 가능한 값: 1–366.
  • ISODOW — ISO 주의 요일. 1 = 월요일, 7 = 일요일.
  • ISOYEAR — ISO 8601 주 번호 연도.
  • CENTURY — 세기. 예를 들어 연도 2024는 21세기에 속합니다.
  • DECADE — 10년 단위(연도를 10으로 나눈 값). 예를 들어 연도 2024의 decade는 202예요.
  • MILLENNIUM — 밀레니엄. 예를 들어 연도 2024는 3번째 밀레니엄에 속합니다.
  • TIMEZONE_HOUR — 피연산자 시간대의 UTC 오프셋의 부호 있는 시간 부분. 예를 들어 +5:30은 5, -3:30은 -3 을 반환합니다.
  • TIMEZONE_MINUTE — 피연산자 시간대의 UTC 오프셋의 부호 있는 분 부분. 예를 들어 +5:30은 30, -3:30은 -30 을 반환합니다.

part 매개변수는 대소문자를 구분하지 않아요. date 매개변수는 처리할 값을 지정합니다. Date, Date32, DateTime, DateTime64, Interval 타입이 지원됩니다. dateInterval이면, 요청한 part가 간격의 저장된 종류와 일치해야 해요(예: EXTRACT(DAY FROM INTERVAL 5 DAY)는 허용되고, EXTRACT(HOUR FROM INTERVAL 5 DAY)는 ClickHouse 간격이 단일 종류이므로 거부됩니다). Interval 피연산자의 결과는 Int64예요. Examples:

SELECT EXTRACT(DAY FROM toDate('2017-06-15'));
SELECT EXTRACT(MONTH FROM toDate('2017-06-15'));
SELECT EXTRACT(YEAR FROM toDate('2017-06-15'));
SELECT EXTRACT(EPOCH FROM toDateTime('2024-01-15 12:30:45', 'UTC'));
SELECT EXTRACT(DOW FROM toDate('2024-01-15'));
SELECT EXTRACT(CENTURY FROM toDate('2024-01-01'));
SELECT EXTRACT(TIMEZONE_HOUR   FROM toDateTime('2024-01-15 12:00:00', 'Asia/Kolkata'));    -- 5
SELECT EXTRACT(TIMEZONE_MINUTE FROM toDateTime('2024-01-15 12:00:00', 'Asia/Kolkata'));    -- 30
SELECT EXTRACT(DAY   FROM INTERVAL 40 DAY);                                                -- 40
SELECT EXTRACT(MONTH FROM INTERVAL 7 MONTH);                                               -- 7

다음 예시에서는 테이블을 만들고 DateTime 타입의 값을 삽입합니다.

CREATE TABLE test.Orders
(
    OrderId UInt64,
    OrderName String,
    OrderDate DateTime
) ENGINE = MergeTree
ORDER BY ();
INSERT INTO test.Orders VALUES (1, 'Jarlsberg Cheese', toDateTime('2008-10-11 13:23:44'));
SELECT
    toYear(OrderDate) AS OrderYear,
    toMonth(OrderDate) AS OrderMonth,
    toDayOfMonth(OrderDate) AS OrderDay,
    toHour(OrderDate) AS OrderHour,
    toMinute(OrderDate) AS OrderMinute,
    toSecond(OrderDate) AS OrderSecond
FROM test.Orders;
┌─OrderYear─┬─OrderMonth─┬─OrderDay─┬─OrderHour─┬─OrderMinute─┬─OrderSecond─┐
│      2008 │         10 │       11 │        13 │          23 │          44 │
└───────────┴────────────┴──────────┴───────────┴─────────────┴─────────────┘

더 많은 예시는 tests에서 볼 수 있어요.

INTERVAL

DateDateTime 타입 값과의 산술 연산에 사용해야 할 Interval 타입 값을 생성해요. 간격 타입:

  • SECOND
  • MINUTE
  • HOUR
  • DAY
  • WEEK
  • MONTH
  • QUARTER
  • YEAR

INTERVAL 값을 설정할 때 문자열 리터럴을 사용할 수도 있어요. 예를 들어 INTERVAL 1 HOURINTERVAL '1 hour' 또는 INTERVAL '1' hour와 동일합니다. 서로 다른 타입의 간격은 결합할 수 없어요. INTERVAL 4 DAY 1 HOUR 같은 표현식은 사용할 수 없습니다. 간격의 가장 작은 단위보다 작거나 같은 단위로 지정하세요. 예를 들어 INTERVAL 25 HOUR. 아래 예시처럼 연속 연산을 사용할 수 있어요. Examples:

SELECT now() AS current_date_time, current_date_time + INTERVAL 4 DAY + INTERVAL 3 HOUR;
┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
│ 2020-11-03 22:09:50 │                                    2020-11-08 01:09:50 │
└─────────────────────┴────────────────────────────────────────────────────────┘
SELECT now() AS current_date_time, current_date_time + INTERVAL '4 day' + INTERVAL '3 hour';
┌───current_date_time─┬─plus(plus(now(), toIntervalDay(4)), toIntervalHour(3))─┐
│ 2020-11-03 22:12:10 │                                    2020-11-08 01:12:10 │
└─────────────────────┴────────────────────────────────────────────────────────┘
SELECT now() AS current_date_time, current_date_time + INTERVAL '4' day + INTERVAL '3' hour;
┌───current_date_time─┬─plus(plus(now(), toIntervalDay('4')), toIntervalHour('3'))─┐
│ 2020-11-03 22:33:19 │                                        2020-11-08 01:33:19 │
└─────────────────────┴────────────────────────────────────────────────────────────┘

INTERVAL 문법이나 addDays 함수가 항상 선호됩니다. 단순 덧셈이나 뺄셈(now() + ... 같은 문법)은 시간 설정(예: 일광 절약 시간)을 고려하지 않아요. Examples:

SELECT toDateTime('2014-10-26 00:00:00', 'Asia/Istanbul') AS time, time + 60 * 60 * 24 AS time_plus_24_hours, time + toIntervalDay(1) AS time_plus_1_day;
┌────────────────time─┬──time_plus_24_hours─┬─────time_plus_1_day─┐
│ 2014-10-26 00:00:00 │ 2014-10-26 23:00:00 │ 2014-10-27 00:00:00 │
└─────────────────────┴─────────────────────┴─────────────────────┘

See Also- Interval data type

  • toInterval type conversion functions

Date and Time Addition

Date 또는 Date32 값은 + 연산자로 Time 또는 Time64 값과 더할 수 있어요. 결과는 주어진 시각의 날짜를 나타내는 DateTime 또는 DateTime64입니다. 연산은 가환적이에요. 결과 타입은 피연산자 타입에 따라 달라집니다:

Left operand Right operand Result type
Date Time DateTime
Date Time64(s) DateTime64(s)
Date32 Time DateTime64(0)
Date32 Time64(s) DateTime64(s)

결과는 세션 시간대(세션 시간대가 없으면 서버 기본 시간대)를 사용합니다. date_time_overflow_behavior 설정이 결과가 표현 가능한 범위를 벗어날 때 무엇을 하는지 제어합니다. Examples:

SET use_legacy_to_time = 0;
SELECT toDate('2024-07-15') + toTime('14:30:25') AS dt, toTypeName(dt);
┌──────────────────dt─┬─toTypeName(dt)─┐
│ 2024-07-15 14:30:25 │ DateTime       │
└─────────────────────┴────────────────┘
SELECT toDate('2024-07-15') + toTime64('14:30:25.123456', 6) AS dt, toTypeName(dt);
┌─────────────────────────dt─┬─toTypeName(dt)─┐
│ 2024-07-15 14:30:25.123456 │ DateTime64(6)  │
└────────────────────────────┴────────────────┘
SELECT toTime64('23:59:59.999', 3) + toDate32('2024-07-15') AS dt, toTypeName(dt);
┌──────────────────────dt─┬─toTypeName(dt)─┐
│ 2024-07-15 23:59:59.999 │ DateTime64(3)  │
└─────────────────────────┴────────────────┘

AT TIME ZONE and AT LOCAL

후위 연산자 AT TIME ZONEAT LOCALDateTime 또는 DateTime64 값을 다른 시간대로 변환해요. 이들은 기존 toTimeZone 함수의 문법적 설탕입니다:

Syntax Equivalent
expr AT TIME ZONE zone toTimeZone(expr, zone)
expr AT LOCAL toTimeZone(expr, timeZone())

zone은 유효한 시간대 이름으로 평가되는 어떤 상수 문자열 표현식이든 될 수 있어요(예: 'America/Denver', 'UTC', 또는 concat('America', '/', 'Denver')). AT TIME ZONEtoTimeZone으로 축약되므로 같은 시간대 인자 규칙이 적용됩니다. 열 참조 같은 상수가 아닌 표현식에는 allow_nonconst_timezone_arguments = 1이 필요합니다. AT LOCAL은 현재 세션 시간대(없으면 서버 기본값)를 사용합니다. Distributed 테이블에서는 session_timezone을 명시적으로 설정해야 하며, 비어 있으면 timeZone()이 샤드 로컬이어서 상수 toTimeZone 인자로 사용할 수 없어 ILLEGAL_COLUMN 예외가 발생합니다. PostgreSQL의 timestamp without time zone AT TIME ZONE zone이 변환 전에 벽시계 값을 주어진 시간대의 값으로 재해석하는 것과 달리, ClickHouse는 항상 같은 절대 시점을 유지하고 표시에 사용되는 시간대 라벨만 바꿉니다. 두 형태 모두 toTimeZone과 동등하며 기본 타임스탬프를 변경하지 않아요. AT TIME ZONE은 PostgreSQL과 일치하게 연산자 우선순위 13을 가집니다(12인 *///%보다, 11인 +/-보다 높음). 따라서 a * ts AT TIME ZONE 'tz'a * (ts AT TIME ZONE 'tz')로, ts + interval AT TIME ZONE 'tz'ts + (interval AT TIME ZONE 'tz')로 묶입니다. 산술 후에 시간대 변환을 적용하려면 명시적 괄호를 사용하세요:

-- Explicit parens required to add first, then convert timezone
SELECT (TIMESTAMP '2001-02-16 20:38:40' + INTERVAL 1 HOUR) AT TIME ZONE 'America/Denver';
-- Equivalent to:
SELECT toTimeZone(TIMESTAMP '2001-02-16 20:38:40' + INTERVAL 1 HOUR, 'America/Denver');

Examples:

SET session_timezone = 'UTC';

SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver';
┌─toTimeZone(toDateTime('2001-02-16 20:38:40'), 'America/Denver')─┐
│ 2001-02-16 13:38:40                                              │
└──────────────────────────────────────────────────────────────────┘
SELECT TIMESTAMP '2001-02-16 20:38:40' AT LOCAL;
┌─toTimeZone(toDateTime('2001-02-16 20:38:40'), timeZone())─┐
│ 2001-02-16 20:38:40                                        │
└────────────────────────────────────────────────────────────┘

See Also- toTimeZone

  • timeZone

Logical AND Operator

문법 SELECT a AND band 함수로 ab의 논리곱을 계산합니다.

Logical OR Operator

문법 SELECT a OR bor 함수로 ab의 논리합을 계산합니다.

Logical Negation Operator

문법 SELECT NOT anot 함수로 a의 논리 부정을 계산합니다.

Conditional Operator

a ? b : cif(a, b, c) 함수. 참고: 조건 연산자는 b와 c의 값을 계산한 다음 조건 a가 충족되는지 확인하고 해당 값을 반환합니다. b 또는 CarrayJoin() 함수면, "a" 조건과 무관하게 각 행이 복제됩니다.

Conditional Expression

CASE [x]
    WHEN a THEN b
    [WHEN ... THEN ...]
    [ELSE c]
END

x가 지정되면 transform(x, [a, ...], [b, ...], c) 함수가 사용됩니다. 그렇지 않으면 multiIf(a, b, ..., c)를 사용해요. 표현식에 ELSE c 절이 없으면 기본값은 NULL입니다. transform 함수는 NULL과 함께 동작하지 않습니다.

Concatenation Operator

s1 || s2concat(s1, s2) 함수.

Lambda Creation Operator

x -> exprlambda(x, expr) 함수. 다음 연산자들은 괄호이므로 우선순위가 없습니다:

Array Creation Operator

[x1, ...]array(x1, ...) 함수.

Tuple Creation Operator

(x1, x2, ...)tuple(x2, x2, ...) 함수.

Associativity

모든 이항 연산자는 왼쪽 결합입니다. 예를 들어 1 + 2 + 3plus(plus(1, 2), 3)으로 변환됩니다. 때로는 기대와 다르게 동작할 수 있어요. 예를 들어 SELECT 4 > 2 > 3은 0이 됩니다. 효율성을 위해 andor 함수는 인자를 몇 개든 받아들입니다. 대응하는 ANDOR 연산자 체인은 이 함수들의 단일 호출로 변환됩니다.

Checking for NULL

ClickHouse는 IS NULLIS NOT NULL 연산자를 지원합니다.

IS NULL

  • Nullable 타입 값의 경우 IS NULL 연산자는 값이 NULL이면 1, 그렇지 않으면 0 을 반환해요.
  • 다른 값의 경우 IS NULL 연산자는 항상 0 을 반환합니다.

optimize_functions_to_subcolumns 설정을 활성화해 최적화할 수 있어요. optimize_functions_to_subcolumns = 1이면 함수는 전체 열 데이터를 읽고 처리하는 대신 null 하위 열만 읽습니다. SELECT n IS NULL FROM table 쿼리는 SELECT n.null != 0 FROM TABLE로 변환됩니다.

SELECT x+100 FROM t_null WHERE y IS NULL
┌─plus(x, 100)─┐
│          101 │
└──────────────┘

IS NOT NULL

  • Nullable 타입 값의 경우 IS NOT NULL 연산자는 값이 NULL이면 0, 그렇지 않으면 1 을 반환해요.
  • 다른 값의 경우 IS NOT NULL 연산자는 항상 1 을 반환합니다.
SELECT * FROM t_null WHERE y IS NOT NULL
┌─x─┬─y─┐
│ 2 │ 3 │
└───┴───┘

optimize_functions_to_subcolumns 설정을 활성화해 최적화할 수 있어요. optimize_functions_to_subcolumns = 1이면 함수는 전체 열 데이터를 읽고 처리하는 대신 null 하위 열만 읽습니다. SELECT n IS NOT NULL FROM table 쿼리는 SELECT NOT n.null FROM TABLE로 변환됩니다.

Checking Boolean Values

ClickHouse는 IS TRUE, IS FALSE, IS UNKNOWN, IS NOT TRUE, IS NOT FALSE, IS NOT UNKNOWN 연산자를 지원합니다. 이들은 BoolNullable(Bool) 표현식과 함께 사용됩니다.

  • expr IS TRUE 는 expr 이 true 인 경우에만 1 을 반환해요.
  • expr IS FALSE 는 expr 이 false 인 경우에만 1 을 반환해요.
  • expr IS UNKNOWN 은 expr 이 NULL 인 경우에만 1 을 반환해요.
  • expr IS NOT TRUE 는 expr 이 false 또는 NULL 이면 1 을 반환해요.
  • expr IS NOT FALSE 는 expr 이 true 또는 NULL 이면 1 을 반환해요.
  • expr IS NOT UNKNOWN 은 expr 이 NULL 이 아니면 1 을 반환해요.

불리언 표현식에서 IS UNKNOWNIS NULL과, IS NOT UNKNOWNIS NOT NULL과 동등합니다.

CREATE TABLE t_bool (x Nullable(Bool)) ENGINE = Memory;
INSERT INTO t_bool VALUES (true), (false), (NULL);

SELECT
    x,
    x IS TRUE,
    x IS FALSE,
    x IS UNKNOWN,
    x IS NOT TRUE,
    x IS NOT FALSE,
    x IS NOT UNKNOWN
FROM t_bool;

더 알아보기 (Learn more)