mcpField
Q
query

query

github.com/duckdbデータ・データベース6131.5k 回インストール28 週間前に更新
リポジトリ

query について

DuckDB でファイルや保存済みセッションのデータを検索するスキルです。自然言語から SQL を作成し、結果サイズを確認してから実行し、結果の解釈やエラー対応も行います。

主な機能

  1. 01保存済みセッションと単発モードの判定
  2. 02自然言語から SQL を生成
  3. 03実行前の結果サイズ推定
  4. 04ファイルクエリのサンドボックス実行
  5. 05結果の解釈とエラー対応

活用シーン

  1. 01CSV や Parquet ファイルの検索
  2. 02保存済みセッションのテーブル調査
  3. 03自然言語の質問への SQL による回答

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/duckdb/duckdb-skills --skill query

インストール後、Claude Code で/queryを入力して読み込まれたか確認します。

詳細

DuckDB を使用してユーザーのデータ検索を支援します。

入力:$@

以下の手順を順番に実行します。

ステップ 1 — 状態を解決し、モードを決定する

次のいずれかの場所に既存の状態ファイルがあるか確認します。

STATE_DIR=""
test -f .duckdb-skills/state.sql && STATE_DIR=".duckdb-skills"
PROJECT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
PROJECT_ID="$(echo "$PROJECT_ROOT" | tr '/' '-')"
test -f "$HOME/.duckdb-skills/$PROJECT_ID/state.sql" && STATE_DIR="$HOME/.duckdb-skills/$PROJECT_ID"

見つかった場合は、参照先のデータベースに引き続きアクセスできることを確認します。

duckdb -init "$STATE_DIR/state.sql" -c "SHOW DATABASES;"

次に、モードを決定します。

  • アドホックモード:--file フラグが指定されている場合、SQL でファイルパス/リテラルが参照されている場合(例:FROM 'data.csv')、または STATE_DIR が空の場合。
  • セッションモード:STATE_DIR が設定されており、入力でテーブル名が参照されている場合、自然言語の場合、またはファイル参照を含まない SQL の場合。

状態ファイルが存在せず、ファイルも参照されていない場合は、:memory: を対象とするアドホックモードに切り替えます。この場合、ユーザーは SQL でファイルを直接参照する必要があります。

状態ファイルが存在するものの、ファイル内の ATTACH が失敗した場合は、ユーザーに警告してアドホックモードに切り替えます。

ステップ 2 — DuckDB がインストールされているか確認する

command -v duckdb

見つからない場合は、/duckdb-skills:install-duckdb に処理を委任してから続行します。

ステップ 3 — 必要に応じて SQL を生成する

入力が自然言語(有効な SQL ではない)の場合は、以下の Friendly SQL リファレンスを使用して SQL を生成します。

セッションモードでは、クエリ生成に必要な情報を得るため、最初にスキーマを取得します。

duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name FROM duckdb_tables() ORDER BY table_name;
"

次に、関連するテーブルについて以下を実行します。

duckdb -init "$STATE_DIR/state.sql" -csv -c "DESCRIBE <table_name>;"

スキーマの情報と Friendly SQL リファレンスを使用して、最適なクエリを生成します。

ステップ 4 — 結果のサイズを推定する

実行前に、クエリが非常に大きな結果を生成し、この会話に返す際に過剰なトークンを消費する可能性があるか推定します。

セッションモード — 対象テーブルの行数を確認します。

duckdb -init "$STATE_DIR/state.sql" -csv -c "
SELECT table_name, estimated_size, column_count
FROM duckdb_tables()
WHERE table_name IN ('<table1>', '<table2>');
"

アドホックモード — データソースを調べます。

duckdb :memory: -csv -c "
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
SELECT count() AS row_count FROM 'FILE_PATH';
"

評価:

  • クエリに LIMIT、count()、または出力を制限するその他の集計がすでに含まれている場合 → 安全です。そのまま続行します。
  • データソースが 100 万行を超え、クエリに LIMIT または集計が含まれていない場合は、ユーザーに次のように伝えます。 「このクエリは非常に大きな結果セットを返す可能性があります。ここに表示すると多くのトークンを消費し、コストも増加します。LIMIT 1000 または集計を追加して、出力を扱いやすくすることをおすすめします。」 そのまま実行してよいか、確認を求めます。
  • データサイズが 10 GB を超える場合は、さらに次のように警告します。 「このテーブルは 10 GB を超えているため、クエリの完了に時間がかかる場合があります。」 ユーザーが確認したら続行します。

DESCRIBE、SUMMARIZE、集計、count() など、本質的に結果が制限されているクエリでは、この手順を省略します。

ステップ 5 — クエリを実行する

アドホックモード(サンドボックス化され、参照されたファイルのみアクセス可能):

duckdb :memory: -csv <<'SQL'
SET allowed_paths=['FILE_PATH'];
SET enable_external_access=false;
SET allow_persistent_secrets=false;
SET lock_configuration=true;
<QUERY>;
SQL

FILE_PATH を、クエリまたは --file 引数から抽出した実際のファイルパスに置き換えます。 複数のファイルが参照されている場合は、すべてのパスを allowed_paths リストに含めます。

セッションモード(ユーザーが信頼するデータベース):

duckdb -init "$STATE_DIR/state.sql" -csv -c "<QUERY>"

複数行のクエリでは、-init とヒアドキュメントを使用します。

duckdb -init "$STATE_DIR/state.sql" -csv <<'SQL'
<QUERY>;
SQL

シェルのクォートに関する問題を避けるため、複数行のクエリには必ずヒアドキュメント(<<'SQL')を使用します。

ステップ 6 — エラーに対処する

  • 構文エラー:エラーを表示し、修正したクエリを提案して再実行します。
  • 拡張機能が見つからない場合(例:Extension "X" not loaded):/duckdb-skills:install-duckdb <ext> に処理を委任してから再試行します。
  • テーブルが見つからない場合(セッションモード):FROM duckdb_tables() を使って利用可能なテーブルを一覧表示し、修正案を提案します。
  • ファイルが見つからない場合(アドホックモード):find "$PWD" -name "<filename>" 2>/dev/null を使ってファイルを検索し、修正したパスを提案します。
  • DuckDB エラーが解消しない場合、または内容が不明確な場合:/duckdb-skills:duckdb-docs <error message or relevant keywords> を使用して、解決方法をドキュメントで検索してから、修正を適用して再試行します。

ステップ 7 — 結果を提示する

クエリの出力をユーザーに表示します。結果が 100 行を超える場合は、出力が切り詰められていることを伝え、クエリに LIMIT を追加するよう提案します。

自然言語の質問の場合は、結果の簡単な解釈も提示します。


DuckDB Friendly SQL リファレンス

SQL を生成する際は、以下の DuckDB の慣用的な構文を優先します。

コンパクトな句
  • FROM を先に記述:FROM table WHERE x > 10(暗黙の SELECT *)
  • GROUP BY ALL:集約関数以外のすべての列で自動的にグループ化します
  • ORDER BY ALL:決定的な結果を得るため、すべての列で並べ替えます
  • SELECT * EXCLUDE (col1, col2):ワイルドカードから列を除外します
  • SELECT * REPLACE (expr AS col):列をその場で変換します
  • UNION ALL BY NAME:列の順序が異なるテーブルを結合します
  • 割合で指定する LIMIT:LIMIT 10% は行の割合を返します
  • プレフィックスエイリアス:SELECT 42 AS x の代わりに SELECT x: 42
  • SELECT リストでは末尾のカンマを使用できます
クエリ機能
  • count():count(*) は不要です
  • 再利用可能なエイリアス:WHERE / GROUP BY / HAVING で列エイリアスを使用します
  • ラテラル列エイリアス:SELECT i+1 AS j, j+2 AS k
  • COLUMNS(*):列全体に式を適用します。正規表現、EXCLUDE、REPLACE、ラムダに対応しています
  • FILTER 句:条件付き集約には count() FILTER (WHERE x > 10) を使用します
  • GROUPING SETS / CUBE / ROLLUP:高度な複数レベルの集約
  • グループごとの上位 N 件:max(col, 3) は上位 3 件をリストで返します。arg_max(arg, val, n)、min_by(arg, val, n) も使用できます
  • DESCRIBE table_name:スキーマの概要(列名と型)
  • SUMMARIZE table_name:統計プロファイルをすぐに表示します
  • PIVOT / UNPIVOT:ワイド形式とロング形式を相互に変換します
  • SET VARIABLE x = expr:SQL レベルの変数を定義し、getvariable('x') で参照します
データのインポート
  • ファイルを直接クエリ:FROM 'file.csv'、FROM 'data.parquet'
  • グロブ:FROM 'data/part-*.parquet' で複数のファイルを読み込みます
  • 自動検出:CSV のヘッダーとスキーマを自動的に推定します
式と型
  • ドット演算子の連結:'hello'.upper() または col.trim().lower()
  • リスト内包表記:[x*2 FOR x IN list_col]
  • リスト/文字列のスライス:col[1:3]、負のインデックス col[-1]
  • STRUCT. 記法*:SELECT s.* FROM (SELECT {'a': 1, 'b': 2} AS s)
  • 角括弧のリスト:[1, 2, 3]
  • format():文字列の書式設定には format('{}->{}', a, b) を使用します
結合
  • ASOF 結合:順序付けされたデータ(タイムスタンプなど)で近似一致させます
  • POSITIONAL 結合:キーではなく位置で行を対応付けます
  • LATERAL 結合:サブクエリ内で先行するテーブル式を参照します
データの変更
  • CREATE OR REPLACE TABLE:事前の DROP TABLE IF EXISTS は不要です
  • CREATE TABLE ... AS SELECT(CTAS):クエリ結果からテーブルを作成します
  • INSERT INTO ... BY NAME:位置ではなく名前で列を対応付けます
  • INSERT OR IGNORE INTO / INSERT OR REPLACE INTO:アップサートのパターン

コメント