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

AI を利用した SQL 生成

ClickHouse 25.7 以降では、ClickHouse Clientclickhouse-local に、自然言語による説明を SQL クエリに変換する AI 搭載機能 が含まれています。この機能により、ユーザーはデータ要件を平易なテキストで記述でき、システムがそれに対応する SQL ステートメントへと変換します。

この機能は、複雑な SQL 構文に詳しくないユーザーや、探索的なデータ分析のためにクエリを素早く生成する必要があるユーザーに特に有用です。この機能は標準的な ClickHouse テーブルで動作し、フィルタリング、集約、結合(JOIN)といった一般的なクエリパターンをサポートします。

この処理は、次の組み込みツール/関数の助けを借りて行われます。

  • list_databases - ClickHouse インスタンス内で利用可能なすべてのデータベースを一覧表示
  • list_tables_in_database - 特定のデータベース内のすべてのテーブルを一覧表示
  • get_schema_for_table - 特定のテーブルの CREATE TABLE ステートメント(スキーマ)を取得

前提条件

Anthropic または OpenAI の API キーを環境変数として追加する必要があります。

export ANTHROPIC_API_KEY=your_api_key
export OPENAI_API_KEY=your_api_key

または、設定ファイルを指定することもできます。

ClickHouse SQL playground への接続

この機能を試すにあたっては、ClickHouse SQL playground を使用します。

ClickHouse SQL playground には、次のコマンドを使用して接続できます。

clickhouse client -mn \
--host sql-clickhouse.clickhouse.com \
--secure \
--user demo --password ''
注記

ClickHouse がすでにインストールされていることを前提とします。まだインストールしていない場合は、インストールガイド を参照してください。

自然言語で ClickHouse に質問する

それでは、いくつか質問をしてみましょう。

text-to-SQL 機能は、実質的にワンショットのクエリ生成ツールです。会話履歴を保持しないため、質問の中にできるだけ有用なコンテキストを含めてください。次の点を具体的に指定します:

期間や日付範囲
行いたい分析の種類(平均値、合計、ランキングなど)
適用したいフィルタ条件

住宅価格が高いエリアを見つける

まず住宅価格に関する質問から始めましょう。SQL playground には UK の住宅価格データセットが含まれており、AI が自動的に認識します:

?? 2021年に住宅を購入する際、最も高額な地域はどこか教えていただけますか;

Enter キーを押すと、AI が質問に答えようとする際の思考過程が表示されます。

• スキーマ検出によるAI SQL生成を開始しています...
─────────────────────────────────────────────────
🧠 処理中...[INFO] Text generation successful - model: claude-3-5-sonnet-latest, response_id: msg_01QpQd35ZD8HM9QSYFZuQ8Wh
🔧 呼び出し中: list_databases [toolu_01...]
🧠 処理中✓ list_databases 完了
  └─ 37個のデータベースを検出: - amazon - bluesky - country - covid - default - dns - en...
🔧 呼び出し中: list_databases [toolu_01...]
✓ list_databases 完了
  └─ 37個のデータベースを検出: - amazon - bluesky - country - covid - default - dns - en...
🧠 処理中[INFO] Text generation successful - model: claude-3-5-sonnet-latest, response_id: msg_016DxK8SMVKGrUPfFwi43AzE
🔧 呼び出し中: list_tables_in_database [toolu_01...]
  └─ 引数: {"database":"uk"}
🧠 処理中.✓ list_tables_in_database 完了
  └─ データベース'uk'内に9個のテーブルを検出: - uk_codes - uk_postcode_to_iso - uk_price_p...
🔧 呼び出し中: list_tables_in_database [toolu_01...]
  └─ 引数: {"database":"uk"}
✓ list_tables_in_database 完了
  └─ データベース'uk'内に9個のテーブルを検出: - uk_codes - uk_postcode_to_iso - uk_price_p...
🧠 処理中.[INFO] Text generation successful - model: claude-3-5-sonnet-latest, response_id: msg_015giF12wm619beNGC5aTrmw
🔧 呼び出し中: get_schema_for_table [toolu_01...]
  └─ 引数: {"database":"uk","table":"uk_price_paid"}
✓ get_schema_for_table 完了
  └─ uk.uk_price_paidのスキーマ: CREATE TABLE uk.uk_price_paid (     `price` UInt...
🔧 呼び出し中: get_schema_for_table [toolu_01...]
  └─ 引数: {"database":"uk","table":"uk_price_paid"}
🧠 処理中..✓ get_schema_for_table 完了
  └─ uk.uk_price_paidのスキーマ: CREATE TABLE uk.uk_price_paid (     `price` UInt...
🧠 処理中[INFO] Text generation successful - model: claude-3-5-sonnet-latest, response_id: msg_01HxT1HKbaTT3165Wx5bDtY9
─────────────────────────────────────────────────
• ✨ SQLクエリの生成が完了しました!
:) SELECT     town,     district,     county,     round(avg(price), 2) as avg_price,     count() as total_sales FROM uk.uk_price_paid WHERE date >= '2021-01-01' AND date <= '2021-12-31' GROUP BY     town,     district,     county HAVING total_sales >= 10 ORDER BY avg_price DESC LIMIT 10

AI は次の手順で処理を行います。

  1. スキーマ検出 - 利用可能なデータベースとテーブルを探索する
  2. テーブル解析 - 関連するテーブルの構造を調べる
  3. クエリ生成 - 質問内容と検出したスキーマに基づいて SQL を生成する

ここで、uk_price_paid テーブルが見つかり、実行用のクエリが生成されていることが分かります。 そのクエリを実行すると、次のような出力が得られます。

┌─町─────────────┬─地区───────────────────┬─郡──────────────┬──平均価格─┬─総売上高───┐
│ ILKLEY         │ HARROGATE              │ NORTH YORKSHIRE │    4310200 │          10 │
│ LONDON         │ CITY OF LONDON         │ GREATER LONDON  │ 4008117.32 │         311 │
│ LONDON         │ CITY OF WESTMINSTER    │ GREATER LONDON  │ 2847409.81 │        3984 │
│ LONDON         │ KENSINGTON AND CHELSEA │ GREATER LONDON  │  2331433.1 │        2594 │
│ EAST MOLESEY   │ RICHMOND UPON THAMES   │ GREATER LONDON  │ 2244845.83 │          12 │
│ LEATHERHEAD    │ ELMBRIDGE              │ SURREY          │ 2051836.42 │         102 │
│ VIRGINIA WATER │ RUNNYMEDE              │ SURREY          │ 1914137.53 │         169 │
│ REIGATE        │ MOLE VALLEY            │ SURREY          │ 1715780.89 │          18 │
│ BROADWAY       │ TEWKESBURY             │ GLOUCESTERSHIRE │ 1633421.05 │          19 │
│ OXFORD         │ SOUTH OXFORDSHIRE      │ OXFORDSHIRE     │ 1628319.07 │         405 │
└────────────────┴────────────────────────┴─────────────────┴────────────┴─────────────┘

フォローアップの質問をしたい場合は、質問を最初から組み立て直す必要があります。

グレーター・ロンドンにおける高額な物件の特定

この機能は会話履歴を保持しないため、各クエリは自己完結している必要があります。フォローアップの質問をする際には、以前のクエリに言及するのではなく、必要なコンテキストをすべて含めて指定する必要があります。 たとえば、前の結果を確認したあとで、グレーター・ロンドンの物件に絞り込みたくなるかもしれません。「グレーター・ロンドンはどうですか?」とだけ尋ねるのではなく、次のように完全なコンテキストを含める必要があります。

?? グレーター・ロンドンで年次ごとに住宅価格が最も高い地域を教えてください;

AI はこのデータを見たばかりなのに、同じ探索プロセスをもう一度実行していることに注目してください。

• AI SQL生成をスキーマ検出と共に開始しています...
─────────────────────────────────────────────────
🧠 思考中[INFO] テキスト生成成功 - モデル: claude-3-5-sonnet-latest, response_id: msg_012m4ayaSHTYtX98gxrDy1rz
🔧 呼び出し中: list_databases [toolu_01...]
✓ list_databases 完了
  └─ 37個のデータベースを検出: - amazon - bluesky - country - covid - default - dns - en...
🔧 呼び出し中: list_databases [toolu_01...]
🧠 思考中.✓ list_databases 完了
  └─ 37個のデータベースを検出: - amazon - bluesky - country - covid - default - dns - en...
🧠 思考中.[INFO] テキスト生成成功 - モデル: claude-3-5-sonnet-latest, response_id: msg_01KU4SZRrJckutXUzfJ4NQtA
🔧 呼び出し中: list_tables_in_database [toolu_01...]
  └─ 引数: {"database":"uk"}
🧠 思考中..✓ list_tables_in_database 完了
  └─ データベース 'uk' 内に9個のテーブルを検出: - uk_codes - uk_postcode_to_iso - uk_price_p...
🔧 呼び出し中: list_tables_in_database [toolu_01...]
  └─ 引数: {"database":"uk"}
✓ list_tables_in_database 完了
  └─ データベース 'uk' 内に9個のテーブルを検出: - uk_codes - uk_postcode_to_iso - uk_price_p...
🧠 思考中[INFO] テキスト生成成功 - モデル: claude-3-5-sonnet-latest, response_id: msg_01X9CnxoBpbD2xj2UzuRy2is
🔧 呼び出し中: get_schema_for_table [toolu_01...]
  └─ 引数: {"database":"uk","table":"uk_price_paid"}
🧠 思考中.✓ get_schema_for_table 完了
  └─ uk.uk_price_paid のスキーマ: CREATE TABLE uk.uk_price_paid (     `price` UInt...
🔧 呼び出し中: get_schema_for_table [toolu_01...]
  └─ 引数: {"database":"uk","table":"uk_price_paid"}
✓ get_schema_for_table 完了
  └─ uk.uk_price_paid のスキーマ: CREATE TABLE uk.uk_price_paid (     `price` UInt...
🧠 思考中...[INFO] テキスト生成成功 - モデル: claude-3-5-sonnet-latest, response_id: msg_01QTMypS1XuhjgVpDir7N9wD
─────────────────────────────────────────────────
• ✨ SQLクエリの生成が完了しました!
:) SELECT     district,     toYear(date) AS year,     round(avg(price), 2) AS avg_price,     count() AS total_sales FROM uk.uk_price_paid WHERE county = 'GREATER LONDON' GROUP BY district, year HAVING total_sales >= 10 ORDER BY avg_price DESC LIMIT 10;

これにより、グレーター・ロンドンのみを対象としてフィルタリングし、結果を年ごとに集計する、より的を絞ったクエリが生成されます。 クエリの実行結果を以下に示します。

┌─district────────────┬─year─┬───avg_price─┬─total_sales─┐
│ CITY OF LONDON      │ 2019 │ 14504772.73 │         299 │
│ CITY OF LONDON      │ 2017 │  6351366.11 │         367 │
│ CITY OF LONDON      │ 2016 │  5596348.25 │         243 │
│ CITY OF LONDON      │ 2023 │  5576333.72 │         252 │
│ CITY OF LONDON      │ 2018 │  4905094.54 │         523 │
│ CITY OF LONDON      │ 2021 │  4008117.32 │         311 │
│ CITY OF LONDON      │ 2025 │  3954212.39 │          56 │
│ CITY OF LONDON      │ 2014 │  3914057.39 │         416 │
│ CITY OF LONDON      │ 2022 │  3700867.19 │         290 │
│ CITY OF WESTMINSTER │ 2018 │  3562457.76 │        3346 │
└─────────────────────┴──────┴─────────────┴─────────────┘

City of London は一貫して「最も高価な地区」として現れています!AI が妥当なクエリを生成していることが分かりますが、結果は時系列ではなく平均価格で並べ替えられています。年ごとの推移を比較するような年次分析を行うには、「各年でもっとも高価な地区」を求めるように質問を言い換えて、結果を別のグループ化で取得するとよいでしょう。