Перейти к основному содержимому
Перейти к основному содержимому

Предложение WHERE

Предложение WHERE позволяет отфильтровать данные, полученные из предложения FROM запроса SELECT.

Если используется предложение WHERE, за ним должно следовать выражение типа UInt8. Строки, для которых это выражение даёт значение 0, исключаются из последующих преобразований или из результата.

Выражение после WHERE часто используется вместе с операторами сравнения и логическими операторами, либо с одной из множества регулярных функций.

Для выражения в WHERE проверяется возможность использования индексов и отсечения партиций, если это поддерживает используемый движок таблицы.

PREWHERE

Существует также оптимизация фильтрации под названием PREWHERE. PREWHERE — это оптимизация для более эффективного применения фильтрации. Она включена по умолчанию, даже если конструкция PREWHERE явно не указана.

Проверка на NULL

Если вам нужно проверить значение на NULL, используйте:

В противном случае выражение с NULL никогда не будет истинным.

Фильтрация данных с помощью логических операторов

Вы можете использовать следующие логические функции в сочетании с предложением WHERE для объединения нескольких условий:

Использование столбцов UInt8 в качестве условия

В ClickHouse столбцы UInt8 могут напрямую использоваться в булевых условиях, где 0 — это false, а любое ненулевое значение (обычно 1) — true. Пример этого приведён в разделе ниже.

Использование операторов сравнения

Можно использовать следующие операторы сравнения:

ОператорФункцияОписаниеПример
a = bequals(a, b)Равноprice = 100
a == bequals(a, b)Равно (альтернативный синтаксис)price == 100
a != bnotEquals(a, b)Не равноcategory != 'Electronics'
a <> bnotEquals(a, b)Не равно (альтернативный синтаксис)category <> 'Electronics'
a < bless(a, b)Меньшеprice < 200
a <= blessOrEquals(a, b)Меньше либо равноprice <= 200
a > bgreater(a, b)Большеprice > 500
a >= bgreaterOrEquals(a, b)Больше либо равноprice >= 500
a LIKE slike(a, b)Сопоставление с шаблоном (с учётом регистра)name LIKE '%top%'
a NOT LIKE snotLike(a, b)Несоответствие шаблону (с учётом регистра)name NOT LIKE '%top%'
a ILIKE silike(a, b)Сопоставление с шаблоном (без учёта регистра)name ILIKE '%LAPTOP%'
a BETWEEN b AND ca >= b AND a <= cПроверка вхождения в диапазон (включительно)price BETWEEN 100 AND 500
a NOT BETWEEN b AND ca < b OR a > cПроверка выхода за пределы диапазонаprice NOT BETWEEN 100 AND 500

Сопоставление с шаблоном и условные выражения

Помимо операторов сравнения, в предложении WHERE можно использовать сопоставление с шаблоном и условные выражения.

FeatureSyntaxCase-SensitivePerformanceBest For
LIKEcol LIKE '%pattern%'YesFastТочное сопоставление с учётом регистра
ILIKEcol ILIKE '%pattern%'NoSlowerПоиск без учёта регистра
if()if(cond, a, b)N/AFastПростые бинарные условия
multiIf()multiIf(c1, r1, c2, r2, def)N/AFastНесколько условий
CASECASE WHEN ... THEN ... ENDN/AFastУсловная логика по стандарту SQL

См. раздел "Сопоставление с шаблоном и условные выражения" с примерами использования.

Выражение с литералами, столбцами или подзапросами

Выражение после предложения WHERE также может включать литералы, столбцы или подзапросы — вложенные операторы SELECT, которые возвращают значения, используемые в условиях.

TypeDefinitionEvaluationPerformanceExample
LiteralФиксированное константное значениеВо время разбора запросаСамое быстроеWHERE price > 100
ColumnСсылка на данные таблицыДля каждой строкиБыстроWHERE price > cost
SubqueryВложенный SELECTВо время выполнения запросаЗависит от подзапросаWHERE id IN (SELECT ...)

Вы можете комбинировать литералы, столбцы и подзапросы в сложных условиях:

-- Literal + Column
WHERE price > 100 AND category = 'Electronics'

-- Column + Subquery
WHERE price > (SELECT AVG(price) FROM products) AND in_stock = true

-- Literal + Column + Subquery
WHERE category = 'Electronics' 
  AND price < 500
  AND id IN (SELECT product_id FROM bestsellers)

-- All three with logical operators
WHERE (price > 100 OR category IN (SELECT category FROM featured))
  AND in_stock = true
  AND name LIKE '%Special%'

Примеры

Проверка на NULL

Запросы со значениями NULL:

CREATE TABLE t_null(x Int8, y Nullable(Int8)) ENGINE=MergeTree() ORDER BY x;
INSERT INTO t_null VALUES (1, NULL), (2, 3);

SELECT * FROM t_null WHERE y IS NULL;
SELECT * FROM t_null WHERE y != 0;
┌─x─┬────y─┐
│ 1 │ ᴺᵁᴸᴸ │
└───┴──────┘
┌─x─┬─y─┐
│ 2 │ 3 │
└───┴───┘

Фильтрация данных с помощью логических операторов

Рассмотрим следующую таблицу и данные:

CREATE TABLE products (
    id UInt32,
    name String,
    price Float32,
    category String,
    in_stock Bool
) ENGINE = MergeTree()
ORDER BY id;

INSERT INTO products VALUES
(1, 'Laptop', 999.99, 'Electronics', true),
(2, 'Mouse', 25.50, 'Electronics', true),
(3, 'Desk', 299.00, 'Furniture', false),
(4, 'Chair', 150.00, 'Furniture', true),
(5, 'Monitor', 350.00, 'Electronics', true),
(6, 'Lamp', 45.00, 'Furniture', false);

1. AND - оба условия должны выполняться:

SELECT * FROM products
WHERE category = 'Electronics' AND price < 500;
   ┌─id─┬─name────┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse   │  25.5 │ Electronics │ true     │
2. │  5 │ Monitor │   350 │ Electronics │ true     │
   └────┴─────────┴───────┴─────────────┴──────────┘

2. OR - должно быть истинно хотя бы одно условие:

SELECT * FROM products
WHERE category = 'Furniture' OR price > 500;
   ┌─id─┬─name───┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Laptop │ 999.99 │ Electronics │ true     │
2. │  3 │ Desk   │    299 │ Furniture   │ false    │
3. │  4 │ Chair  │    150 │ Furniture   │ true     │
4. │  6 │ Lamp   │     45 │ Furniture   │ false    │
   └────┴────────┴────────┴─────────────┴──────────┘

3. NOT — Отрицание условия:

SELECT * FROM products
WHERE NOT in_stock;
   ┌─id─┬─name─┬─price─┬─category──┬─in_stock─┐
1. │  3 │ Desk │   299 │ Furniture │ false    │
2. │  6 │ Lamp │    45 │ Furniture │ false    │
   └────┴──────┴───────┴───────────┴──────────┘

4. XOR - Истинным должно быть ровно одно условие (но не оба):

SELECT *
FROM products
WHERE xor(price > 200, category = 'Electronics')
   ┌─id─┬─name──┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse │  25.5 │ Electronics │ true     │
2. │  3 │ Desk  │   299 │ Furniture   │ false    │
   └────┴───────┴───────┴─────────────┴──────────┘

5. Комбинирование нескольких операторов:

SELECT * FROM products
WHERE (category = 'Electronics' OR category = 'Furniture')
  AND in_stock = true
  AND price < 400;
   ┌─id─┬─name────┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse   │  25.5 │ Electronics │ true     │
2. │  4 │ Chair   │   150 │ Furniture   │ true     │
3. │  5 │ Monitor │   350 │ Electronics │ true     │
   └────┴─────────┴───────┴─────────────┴──────────┘

6. Использование синтаксиса функции:

SELECT * FROM products
WHERE and(or(category = 'Electronics', price > 100), in_stock);
   ┌─id─┬─name────┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Laptop  │ 999.99 │ Electronics │ true     │
2. │  2 │ Mouse   │   25.5 │ Electronics │ true     │
3. │  4 │ Chair   │    150 │ Furniture   │ true     │
4. │  5 │ Monitor │    350 │ Electronics │ true     │
   └────┴─────────┴────────┴─────────────┴──────────┘

Синтаксис с ключевыми словами SQL (AND, OR, NOT, XOR) обычно более читабелен, но синтаксис функций может быть полезен в сложных выражениях или при построении динамических запросов.

Использование столбцов UInt8 в качестве условия

Используя таблицу из предыдущего примера, вы можете использовать имя столбца напрямую в качестве условия:

SELECT * FROM products
WHERE in_stock
   ┌─id─┬─name────┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Laptop  │ 999.99 │ Electronics │ true     │
2. │  2 │ Mouse   │   25.5 │ Electronics │ true     │
3. │  4 │ Chair   │    150 │ Furniture   │ true     │
4. │  5 │ Monitor │    350 │ Electronics │ true     │
   └────┴─────────┴────────┴─────────────┴──────────┘

Использование операторов сравнения

В приведённых ниже примерах используются таблица и данные из примера выше. Результаты опущены для краткости.

1. Явное равенство с true (= 1 или = true):

SELECT * FROM products
WHERE in_stock = true;
-- or
WHERE in_stock = 1;

2. Явное равенство со значением false (= 0 или = false):

SELECT * FROM products
WHERE in_stock = false;
-- or
WHERE in_stock = 0;

3. Неравенство (!= 0 или != false):

SELECT * FROM products
WHERE in_stock != false;
-- or
WHERE in_stock != 0;

4. Больше:

SELECT * FROM products
WHERE in_stock > 0;

5. Меньше или равно:

SELECT * FROM products
WHERE in_stock <= 0;

6. Сочетание с другими условиями:

SELECT * FROM products
WHERE in_stock AND price < 400;

7. Использование оператора IN:

В примере ниже (1, true) — это кортеж.

SELECT * FROM products
WHERE in_stock IN (1, true);

Для этого также можно использовать массив:

SELECT * FROM products
WHERE in_stock IN [1, true];

8. Смешивание стилей сравнения:

SELECT * FROM products
WHERE category = 'Electronics' AND in_stock = true;

Сопоставление с шаблоном и условные выражения

В примерах ниже используются таблица и данные из примера, приведённого выше. Результаты опущены для краткости.

Примеры LIKE

-- Find products with 'o' in the name
SELECT * FROM products WHERE name LIKE '%o%';
-- Result: Laptop, Monitor

-- Find products starting with 'L'
SELECT * FROM products WHERE name LIKE 'L%';
-- Result: Laptop, Lamp

-- Find products with exactly 4 characters
SELECT * FROM products WHERE name LIKE '____';
-- Result: Desk, Lamp

Примеры ILIKE

-- Case-insensitive search for 'LAPTOP'
SELECT * FROM products WHERE name ILIKE '%laptop%';
-- Result: Laptop

-- Case-insensitive prefix match
SELECT * FROM products WHERE name ILIKE 'l%';
-- Result: Laptop, Lamp

Примеры IF

-- Different price thresholds by category
SELECT * FROM products
WHERE if(category = 'Electronics', price < 500, price < 200);
-- Result: Mouse, Chair, Monitor
-- (Electronics under $500 OR Furniture under $200)

-- Filter based on stock status
SELECT * FROM products
WHERE if(in_stock, price > 100, true);
-- Result: Laptop, Chair, Monitor, Desk, Lamp
-- (In stock items over $100 OR all out-of-stock items)

Примеры multiIf

-- Multiple category-based conditions
SELECT * FROM products
WHERE multiIf(
    category = 'Electronics', price < 600,
    category = 'Furniture', in_stock = true,
    false
);
-- Result: Mouse, Monitor, Chair
-- (Electronics < $600 OR in-stock Furniture)

-- Tiered filtering
SELECT * FROM products
WHERE multiIf(
    price > 500, category = 'Electronics',
    price > 100, in_stock = true,
    true
);
-- Result: Laptop, Chair, Monitor, Lamp

Примеры CASE

Простой CASE:

-- Different rules per category
SELECT * FROM products
WHERE CASE category
    WHEN 'Electronics' THEN price < 400
    WHEN 'Furniture' THEN in_stock = true
    ELSE false
END;
-- Result: Mouse, Monitor, Chair

CASE с условиями:

-- Price-based tiered logic
SELECT * FROM products
WHERE CASE
    WHEN price > 500 THEN in_stock = true
    WHEN price > 100 THEN category = 'Electronics'
    ELSE true
END;
-- Result: Laptop, Monitor, Mouse, Lamp