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

Условие 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 ...)

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

-- Литерал + столбец
WHERE price > 100 AND category = 'Electronics'

-- Столбец + подзапрос
WHERE price > (SELECT AVG(price) FROM products) AND in_stock = true

-- Литерал + столбец + подзапрос
WHERE category = 'Electronics' 
  AND price < 500
  AND id IN (SELECT product_id FROM bestsellers)

-- Все три условия с логическими операторами WHERE (price > 100 OR category IN (SELECT category FROM featured)) AND in_stock = true AND name LIKE '%Special%'

## Примеры             \{#examples}

### Проверка на `NULL`                              \{#examples-testing-for-null}

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

```sql
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, 'Ноутбук', 999.99, 'Электроника', true),
(2, 'Мышь', 25.50, 'Электроника', true),
(3, 'Стол', 299.00, 'Мебель', false),
(4, 'Стул', 150.00, 'Мебель', true),
(5, 'Монитор', 350.00, 'Электроника', true),
(6, 'Лампа', 45.00, 'Мебель', false);

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

SELECT * FROM products
WHERE category = 'Electronics' AND price < 500;
   ┌─id─┬─name────┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse   │  25.5 │ Электроника │ true     │
2. │  5 │ Monitor │   350 │ Электроника │ true     │
   └────┴─────────┴───────┴─────────────┴──────────┘

2. OR — хотя бы одно из условий должно выполняться:

SELECT * FROM products
WHERE category = 'Мебель' OR price > 500;
   ┌─id─┬─name───┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Ноутбук │ 999.99 │ Электроника │ true     │
2. │  3 │ Стол   │    299 │ Мебель      │ false    │
3. │  4 │ Стул   │    150 │ Мебель      │ true     │
4. │  6 │ Лампа  │     45 │ Мебель      │ false    │
   └────┴────────┴────────┴─────────────┴──────────┘

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

SELECT * FROM products
WHERE NOT in_stock;
   ┌─id─┬─name─┬─price─┬─category──┬─in_stock─┐
1. │  3 │ Стол │   299 │ Мебель    │ false    │
2. │  6 │ Лампа│    45 │ Мебель    │ false    │
   └────┴──────┴───────┴───────────┴──────────┘

4. XOR — истинным должно быть только одно из условий (но не оба):

SELECT *
FROM products
WHERE xor(price > 200, category = 'Electronics')
   ┌─id─┬─name──┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse │  25.5 │ Электроника │ true     │
2. │  3 │ Desk  │   299 │ Мебель      │ false    │
   └────┴───────┴───────┴─────────────┴──────────┘

5. Сочетание нескольких операторов:

SELECT * FROM products
WHERE (category = 'Электроника' OR category = 'Мебель')
  AND in_stock = true
  AND price < 400;
   ┌─id─┬─name────┬─price─┬─category────┬─in_stock─┐
1. │  2 │ Mouse   │  25.5 │ Электроника │ true     │
2. │  4 │ Chair   │   150 │ Мебель   │ true     │
3. │  5 │ Monitor │   350 │ Электроника │ true     │
   └────┴─────────┴───────┴─────────────┴──────────┘

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

SELECT * FROM products
WHERE and(or(category = 'Electronics', price > 100), in_stock);
   ┌─id─┬─name────┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Ноутбук  │ 999.99 │ Электроника │ true     │
2. │  2 │ Мышь   │   25.5 │ Электроника │ true     │
3. │  4 │ Стул   │    150 │ Мебель   │ true     │
4. │  5 │ Монитор │    350 │ Электроника │ true     │
   └────┴─────────┴────────┴─────────────┴──────────┘

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

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

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

SELECT * FROM products
WHERE in_stock
   ┌─id─┬─name────┬──price─┬─category────┬─in_stock─┐
1. │  1 │ Ноутбук  │ 999.99 │ Электроника │ true     │
2. │  2 │ Мышь   │   25.5 │ Электроника │ true     │
3. │  4 │ Стул   │    150 │ Мебель   │ true     │
4. │  5 │ Монитор │    350 │ Электроника │ true     │
   └────┴─────────┴────────┴─────────────┴──────────┘

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

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

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

SELECT * FROM products
WHERE in_stock = true;
-- или
WHERE in_stock = 1;

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

SELECT * FROM products
WHERE in_stock = false;
-- или
WHERE in_stock = 0;

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

SELECT * FROM products
WHERE in_stock != false;
-- или
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 = 'Электроника' AND in_stock = true;

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

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

Примеры LIKE

-- Найти продукты с буквой 'o' в названии
SELECT * FROM products WHERE name LIKE '%o%';
-- Результат: Laptop, Monitor

-- Найти продукты, начинающиеся с 'L'
SELECT * FROM products WHERE name LIKE 'L%';
-- Результат: Laptop, Lamp

-- Найти продукты с названием из ровно 4 символов
SELECT * FROM products WHERE name LIKE '____';
-- Результат: Desk, Lamp

Примеры использования ILIKE

-- Поиск без учета регистра для 'LAPTOP'
SELECT * FROM products WHERE name ILIKE '%laptop%';
-- Результат: Laptop

-- Совпадение по префиксу без учета регистра
SELECT * FROM products WHERE name ILIKE 'l%';
-- Результат: Laptop, Lamp

Примеры использования IF

-- Различные пороговые значения цены по категориям
SELECT * FROM products
WHERE if(category = 'Electronics', price < 500, price < 200);
-- Результат: Mouse, Chair, Monitor
-- (Электроника дешевле $500 ИЛИ Мебель дешевле $200)

-- Фильтрация по статусу наличия на складе
SELECT * FROM products
WHERE if(in_stock, price > 100, true);
-- Результат: Laptop, Chair, Monitor, Desk, Lamp
-- (Товары в наличии дороже $100 ИЛИ все отсутствующие товары)

Примеры функции multiIf

-- Множественные условия на основе категорий
SELECT * FROM products
WHERE multiIf(
    category = 'Electronics', price < 600,
    category = 'Furniture', in_stock = true,
    false
);
-- Результат: Mouse, Monitor, Chair
-- (Electronics < $600 ИЛИ Furniture в наличии)

-- Многоуровневая фильтрация
SELECT * FROM products
WHERE multiIf(
    price > 500, category = 'Electronics',
    price > 100, in_stock = true,
    true
);
-- Результат: Laptop, Chair, Monitor, Lamp

Примеры конструкции CASE

Простой пример CASE:

-- Различные правила для каждой категории
SELECT * FROM products
WHERE CASE category
    WHEN 'Electronics' THEN price < 400
    WHEN 'Furniture' THEN in_stock = true
    ELSE false
END;
-- Результат: Mouse, Monitor, Chair

CASE с условиями поиска:

-- Многоуровневая логика на основе цены
SELECT * FROM products
WHERE CASE
    WHEN price > 500 THEN in_stock = true
    WHEN price > 100 THEN category = 'Electronics'
    ELSE true
END;
-- Результат: Laptop, Monitor, Mouse, Lamp