メインコンテンツへスキップ
メインコンテンツへスキップ

WHERE 句

WHERE 句は、SELECTFROM 句から得られるデータをフィルタリングするために使用します。

WHERE 句がある場合、その直後には UInt8 型の式を記述する必要があります。 この式が 0 と評価された行は、その後の変換処理や結果から除外されます。

WHERE 句に続く式は、比較演算子論理演算子、あるいは多数存在する 汎用関数 のいずれかと組み合わせて使用されることがよくあります。

WHERE 式は、基盤となるテーブルエンジンがそれをサポートしている場合、インデックスの利用やパーティションプルーニングの可否を考慮して評価されます。

PREWHERE

PREWHERE と呼ばれるフィルタリングの最適化も存在します。 PREWHERE は、フィルタリングをより効率的に適用するための最適化です。 PREWHERE 句が明示的に指定されていなくても、デフォルトで有効になっています。

NULL の判定

値がNULLかどうかを判定する必要がある場合は、次を使用します。

NULL を含む式は、上記のように明示的に判定しない限り、真になることはありません。

論理演算子を使用したデータのフィルタリング

複数の条件を組み合わせて指定するために、WHERE 句と組み合わせて次の論理関数を使用できます:

条件としての UInt8 カラムの使用

ClickHouse では、UInt8 カラムをブール条件として直接使用でき、0false、それ以外の非ゼロ値 (一般的には 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 句ではパターンマッチングと条件式も使用できます。

機能構文大文字小文字の区別パフォーマンス最適な用途
LIKEcol LIKE '%pattern%'あり高速大文字小文字を区別するパターンマッチング
ILIKEcol ILIKE '%pattern%'なしやや低速大文字小文字を区別しない検索
if()if(cond, a, b)該当なし高速単純な二項条件
multiIf()multiIf(c1, r1, c2, r2, def)該当なし高速複数条件
CASECASE WHEN ... THEN ... END該当なし高速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 - 少なくとも1つの条件が成立している必要があります:

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 キーワード構文 (ANDORNOTXOR) の方が一般的に可読性は高いですが、関数構文は複雑な式や動的クエリを構築する際に有用です。

条件として 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);

この操作は array を使って行うこともできます。

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