Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

構文

このセクションでは、ClickHouse の SQL 構文について見ていきます。 ClickHouse は SQL ベースの構文を採用していますが、さまざまな拡張機能や最適化も提供しています。

クエリのパース

ClickHouse には 2 種類のパーサーがあります。

  • 完全な SQL パーサー (再帰下降パーサー) 。
  • データフォーマットパーサー (高速なストリームパーサー) 。

完全な SQL パーサーは、両方のパーサーを使用する INSERT クエリを除き、すべてのケースで使われます。

以下のクエリを見てみましょう。

INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')

すでに述べたように、INSERTクエリでは 2 種類のパーサーの両方が使われます。 INSERT INTO t VALUES の部分は完全パーサーでパースされ、 データ (1, 'Hello, world'), (2, 'abc'), (3, 'def') はデータフォーマットパーサー、つまり高速ストリームパーサーでパースされます。

完全パーサーを有効にする

input_format_values_interpret_expressions 設定を使うと、 データに対して完全パーサーを有効にすることもできます。

前述の設定が 1 に設定されている場合、 ClickHouse はまず高速ストリームパーサーで値をパースしようとします。 それに失敗すると、ClickHouse はデータを SQL の として扱い、完全パーサーでパースしようとします。

データには任意のフォーマットを使用できます。 クエリを受信すると、server はリクエストのうち max_query_size バイトを超えない部分だけを RAM 上で処理し (デフォルトでは 1 MB) 、残りはストリームとしてパースされます。 これは、大きな INSERTクエリに関する問題を避けるためです。これは、ClickHouse にデータを挿入する推奨方法でもあります。

INSERTクエリで Values フォーマットを使用する場合、 データは SELECTクエリ内の式と同じようにパースされるように見えるかもしれませんが、実際にはそうではありません。 Values フォーマットは、はるかに制限が多くなっています。

この節の残りでは、完全パーサーについて説明します。

空白

  • 構文要素の間には、任意の数の空白文字を入れられます (クエリの先頭と末尾を含む) 。
  • 空白文字には、スペース、タブ、改行、CR、およびフォームフィードが含まれます。

コメント

ClickHouse は、SQL スタイルと C スタイルの両方のコメントをサポートしています。

  • SQL スタイルのコメントは --#!、または # で始まり、行末まで続きます。--#! の後のスペースは省略できます。
  • C スタイルのコメント:
    • // (または / が 3 文字以上連続するもの) の後にテキストを記述し、行末までコメントとして扱われます。/ の後にスペースは不要です。
    • 複数行コメントとして、/* から */ まで記述することもできます。この場合もスペースは不要です。
    • C スタイルのコメントはネストできます。

たとえば:

/*
 * 2つの日付の間の日数を計算します。
 * /* どちらかの引数がNULLの場合はNULLを返します */
 */
SELECT
    dateDiff('day', toDate('2024-01-01'), toDate('2024-12-31')) AS days_in_year, -- 365
    dateDiff('day', toDate('2020-01-01'), today()) AS days_since  #! 2020年以降
    ///////////////////////////////////////////////////////////////////
    # TODO: 時間/分のバリアントを追加する

キーワード

ClickHouse のキーワードは、コンテキストに応じて 大文字と小文字を区別する 場合と 大文字と小文字を区別しない 場合があります。

キーワードが 大文字と小文字を区別しない のは、次に該当するものです。

  • SQL 標準。たとえば、SELECTselectSeLeCt はいずれも有効です。
  • 一般的な DBMS (MySQL や Postgres) の一部実装。たとえば、DateTimedatetime と同じです。

標準 SQL とは異なり、そのほかのすべてのキーワード (関数名を含む) は 大文字と小文字を区別します

また、キーワードは予約語ではありません。 キーワードとして扱われるのは、対応するコンテキストにおいてのみです。 キーワードと同じ名前の 識別子 を使用する場合は、二重引用符またはバッククォートで囲んでください。

たとえば、次のクエリは、テーブル table_name"FROM" という名前のカラムがある場合に有効です。

SELECT "FROM" FROM table_name

識別子

識別子には、次のものがあります。

識別子は引用符で囲むことも囲まないこともできますが、推奨されるのは後者です。

引用符で囲まない識別子は、正規表現 ^[a-zA-Z_][0-9a-zA-Z_]*$ に一致する必要があり、キーワード と同じ名前にはできません。 有効な識別子と無効な識別子の例については、以下の表を参照してください。

有効な識別子 無効な識別子
xyz, _internal, Id_with_underscores_123_ 1x, tom@gmail.com, äußerst_schön

キーワードと同じ名前の識別子を使いたい場合や、識別子に他の記号を使いたい場合は、たとえば "id"`id` のように、二重引用符またはバッククォートで囲んでください。

リテラル

ClickHouse では、リテラルとはクエリ内に直接記述される値のことです。 つまり、クエリの実行中に変化しない固定の値です。

リテラルには次の種類があります。

以下の各セクションで、それぞれについて詳しく見ていきます。

String

文字列リテラルはシングルクォートで囲む必要があります。ダブルクォートはサポートされていません。

エスケープは、次のいずれかの方法で行います。

  • シングルクォート文字 ' の場合に限り、直前にシングルクォートを付けて '' としてエスケープする、または
  • 直前にバックスラッシュを付け、下の表に示すサポートされているエスケープシーケンスを使用する。
サポートされるエスケープ 説明
\xHH 任意個の16進数桁 (H) が続く 8 ビット文字指定。
\N 予約済みで、何もしません (例: SELECT 'a\Nb'ab を返します)
\a ベル
\b バックスペース
\e エスケープ文字
\f 改ページ
\n 改行文字
\r 復帰
\t 水平タブ
\v 垂直タブ
\0 null 文字
\\ バックスラッシュ
\' (or '') シングルクォート
\" ダブルクォート
` バッククォート
\/ スラッシュ
\= 等号
ASCII control characters (c <= 31).

Numeric

数値リテラルは、次のようにパースされます。

  • リテラルの先頭にマイナス記号 - が付いている場合、そのトークンはいったん読み飛ばされ、パース後に結果が負の値にされます。
  • 数値リテラルはまず、strtoull 関数を使って 64 ビット符号なし整数としてパースされます。
    • 値の先頭に 0b または 0x/0X が付いている場合、数値はそれぞれ 2 進数または 16 進数としてパースされます。
    • 値が負で、その絶対値が 263 を超える場合は、エラーが返されます。
  • これに失敗した場合、次に strtod 関数を使って浮動小数点数としてパースされます。
  • それ以外の場合は、エラーが返されます。

リテラル値は、その値が収まる最小の型に CAST されます。 例:

  • 1UInt8 としてパースされます
  • 256UInt16 としてパースされます。

詳細は、データ型 を参照してください。

数値リテラル内のアンダースコア _ は無視され、可読性を高めるために使えます。

次の数値リテラルがサポートされています。

数値リテラル
整数 1, 10_000_000, 18446744073709551615, 01
10 進数 0.1
指数表記 1e100, -1e-100
浮動小数点数 123.456, inf, nan
16 進数 0xc0fe
SQL 標準互換の 16 進文字列 x'c0fe'
2 進数 0b1101
SQL 標準互換の 2 進文字列 b'1101'

複合型

Array は [] で構築します: [1, 2, 3]。Tuple は () で構築します: (1, 'Hello, world!', 2)。 厳密には、これらはリテラルではなく、それぞれ Array 作成演算子および Tuple 作成演算子を使った式です。 Array は少なくとも 1 つの要素を含んでいる必要があり、Tuple は少なくとも 2 つの要素を含んでいる必要があります。

NULL

NULL は、値が存在しないことを示すために使用されます。 テーブルのフィールドに NULL を格納するには、そのフィールドが Nullable 型である必要があります。

ヒアドキュメント

ヒアドキュメント は、元のフォーマットを保ったまま文字列 (多くの場合、複数行) を定義する方法です。 ヒアドキュメント は、2 つの $ 記号の間に置くカスタム文字列リテラルとして定義します。

例えば:

SELECT $heredoc$SHOW CREATE VIEW my_view$heredoc$;

クエリパラメータの定義と使用

クエリパラメータを使用すると、具体的な識別子の代わりに抽象的なプレースホルダーを含む汎用的なクエリを記述できます。 クエリパラメータを含むクエリを実行すると、 すべてのプレースホルダーが解決され、実際のクエリパラメータの値に置き換えられます。

クエリパラメータは、いくつかの方法で定義できます。

  • SET param_<name>=<value> — クエリ内で SET コマンドを使用する方法。
  • --param_<name>='<value>' — コマンドラインで clickhouse-client に引数として渡す方法。
  • param_<name>=<value> — HTTP インターフェイスの URL クエリ文字列パラメータとして指定する方法。

クエリパラメータは、クエリ内で {<name>: <datatype>} を使って参照できます。ここで、<name> はクエリパラメータ名、<datatype> は変換先のデータ型です。

SET コマンドの例

たとえば、次の SQL では abcd という名前のパラメータを定義しており、それぞれ異なるデータ型を持ちます。

SET param_a = 13;
SET param_b = 'str';
SET param_c = '2022-08-04 18:30:53';
SET param_d = {'10': [11, 12], '13': [14, 15]};

SELECT
   {a: UInt32},
   {b: String},
   {c: DateTime},
   {d: Map(String, Array(UInt8))};

13    str    2022-08-04 18:30:53    {'10':[11,12],'13':[14,15]}
clickhouse-client の例

clickhouse-client を使用している場合、パラメータは --param_name=value として指定します。たとえば、次のパラメータの名前は message で、String として取得されます。

clickhouse-client --param_message='hello' --query="SELECT {message: String}"

hello

クエリパラメータが database、table、function、またはその他の識別子の名前を表す場合は、型として Identifier を使用してください。たとえば、次のクエリは uk_price_paid という名前のテーブルから行を返します。

SET param_mytablename = "uk_price_paid";
SELECT * FROM {mytablename:Identifier};
HTTP インターフェイスの例

クエリパラメータは、param_ プレフィックス付きの URL クエリ文字列パラメータとして渡せます。たとえば、次のようになります。

curl -s "http://localhost:8123/?param_message=hello" --data-binary "SELECT {message: String}"

hello
Web UI の例

組み込みの Web UI (play.html) は、クエリ内の {name:Type} 形式のパラメータプレースホルダーを自動的に検出し、各パラメータに対応するラベル付きの入力フィールドを表示します。パラメータ値は HTTP リクエストに含まれ、さらにブックマークや共有のためにページ URL にも保持されます。

関数

関数呼び出しは、識別子に () で囲んだ引数のリスト (空の場合もあります) を続ける形で記述します。 標準SQLとは異なり、引数のリストが空であっても括弧は必須です。 例:

now()

以下もあります:

一部の集約関数では、括弧内に 2 つの引数リストを指定できます。例:

quantile (0.9)(x) 

これらの集約関数は「パラメトリック」関数と呼ばれ、 最初のリストにある引数は「パラメーター」と呼ばれます。

演算子

演算子は、クエリのパース時に、優先順位と結合規則を考慮して対応する関数に変換されます。

たとえば、次の式では

1 + 2 * 3 + 4

に変換されます

plus(plus(1, multiply(2, 3)), 4)`

データ型とデータベースのテーブルエンジン

CREATEクエリ内のデータ型とテーブルエンジンは、識別子や関数と同じように記述します。 つまり、括弧付きの引数リストを含むことも、含まないこともあります。

詳細については、以下のセクションを参照してください。

式には、次のいずれかを指定できます。

  • 関数
  • 識別子
  • リテラル
  • 演算子の適用
  • 括弧で囲まれた式
  • サブクエリ
  • アスタリスク

また、別名を含めることもできます。

式のリストとは、1 つ以上の式をカンマで区切ったものです。 関数や演算子は、その引数として式を取ることもできます。

定数式とは、クエリ解析中、つまり実行前に結果が判明している式です。 たとえば、リテラルに対する式は定数式です。

式の別名

別名とは、クエリ内のに付けるユーザー定義の名前です。

expr AS alias

上記の構文の各部分について、以下で説明します。

構文の要素 説明 Example 注記
AS 別名を定義するためのキーワードです。AS キーワードを使わなくても、SELECT 句でテーブル名またはカラム名に別名を付けることができます。 SELECT table_name_alias.column_name FROM table_name table_name_alias. CAST 関数では、AS キーワードは別の意味で使われます。関数の説明を参照してください。
expr ClickHouse でサポートされる任意の式です。 SELECT column_name * 2 AS double FROM some_table
alias expr に付ける名前です。別名は identifiers の構文に従う必要があります。 SELECT "table t".column_name FROM table_name AS "table t".

使用上の注意

  • 別名はクエリまたはサブクエリ全体で有効で、任意の式に対する別名をクエリ内のどの部分でも定義できます。たとえば、次のようになります。
SELECT (1 AS n) + 2, n`.
  • 別名はサブクエリ内やサブクエリ同士の間では参照できません。たとえば、次のクエリを実行すると、ClickHouse は例外 Unknown identifier: num を返します。
`SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a`
  • サブクエリのSELECT句で結果のカラムに別名が定義されている場合、これらのカラムは外側のクエリから参照できます。たとえば:
SELECT n + m FROM (SELECT 1 AS n, 2 AS m)`.
  • カラム名やテーブル名と同じ別名を付ける場合は注意してください。次の例を見てみましょう。
CREATE TABLE t
(
    a Int,
    b Int
)
ENGINE = TinyLog();

SELECT
    argMax(a, b),
    sum(b) AS b
FROM t;

Received exception from server (version 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: Aggregate function sum(b) is found inside another aggregate function in query.

前の例では、カラム b を持つテーブル t を宣言しました。 次に、データを選択する際に、sum(b) AS b という別名を定義しました。 別名はグローバルであるため、 ClickHouse は式 argMax(a, b) 内の b を式 sum(b) に置き換えました。 この置換によって例外が発生しました。

アスタリスク

SELECTクエリでは、アスタリスクを式の代わりに使用できます。 詳しくは、SELECTのセクションを参照してください。

Navigation