mcpField
D
datahub-sql-workflow

datahub-sql-workflow

github.com/datahub-projectデータ・データベース4541 回インストール4 週間前に更新
リポジトリ

datahub-sql-workflow について

組織内のDataHubの根拠に基づいてSQLクエリを作成するワークフロースキルです。ドキュメント、テーブル規約、スキーマ、保存済みクエリパターンを確認し、生成履歴より整備された業務指針を優先します。

主な機能

  1. 01質問に沿ったSQLコンテキストの検索
  2. 02選択テーブルの規約の確認
  3. 03スキーマ項目と粒度の確認
  4. 04生成パターンより整備済み指針を優先
  5. 05根拠に基づくSQL作成の案内

活用シーン

  1. 01文書化された業務ルールに沿うクエリ作成
  2. 02要求粒度に合うテーブルと結合の選定
  3. 03フィルターと列の意味の検証
  4. 04文書とクエリパターンの不一致の解決

MCP 対応

SQL作成前の根拠収集には、DataHub MCPツール `find_sql_context` と `inspect_tables_for_sql` が必要です。どちらかが使えない場合は、ワークフローを停止するよう定めています。

インストール

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

$npx skills add https://github.com/datahub-project/datahub-skills --skill datahub-sql-workflow

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

詳細

DataHub SQL ワークフロー

すべてのクエリを、DataHub の根拠に基づいて作成してください。その根拠を提供するツールは 2 つあります。

  • find_sql_context(question) はルーティングを行います。質問について組織内で作成されたドキュメント、候補テーブル、それらに関連する保存済みクエリパターンをまとめたカードを返します。
  • inspect_tables_for_sql(table_urns, question) は、選択したテーブルについて、アナリストが適用する規約、各テーブルの厳選ドキュメント、適合する場合は応用できる具体例を返します。

カタログツール(get_entities、list_schema_fields、search)で物理的な構造を確認します。つまり、列が存在するか、その型、粒度を確認します。何が正しいかは業務ドキュメントが示し、アナリストが何をしたかは生成された履歴が示し、何が存在するかはカタログが示します。これらが食い違う場合は、この順序で優先してください(セクション 4)。

find_sql_context と inspect_tables_for_sql は必須です。いずれかがない場合は、処理を中止して、DataHub MCP ツールを有効にするようユーザーに依頼してください。他の検索ツール、ローカルファイル、メモリ、ウェブを代わりに使用してはいけません。それ以外のツールはすべて任意です。ツールを利用できない場合はその旨を伝え、影響しない手順を続けてください。根拠が欠けている場合に推測で補ってはいけません。

1. まず find_sql_context を呼び出し、カード全体を読む

ユーザーがテーブル名やデータセットの URN を指定している場合も含め、他のツールを呼び出す前に find_sql_context(question=<the user's complete question>) を呼び出してください。質問はユーザーが書いたとおりに渡し、キーワードだけに短縮してはいけません。

カードには 5 つの部分があります。次の順に読みます。

  1. authoritative_instructions:{call, results} のグループです。各 call は、すでに実行された search_documents(...) 呼び出し、またはユーザーが編集したアンカー指示です。results は、その呼び出しが返したドキュメントで、それぞれ質問に最も合致する抜粋として示されます。これらは、質問に関する組織独自の見解です。結合キー、最新行のルール、必須フィルター、「このテーブルを使用しないでください」という警告などが含まれます。ほかの内容を読む前に、すべてのグループを確認してください。
  2. authoritative_instructions_note:グループの作成方法と、さらに詳しく調べる方法を示します。その指示に従ってください。
  3. candidate_tables:根拠が示すテーブルです。それぞれに tier(blessed または reviewed は人が検証済み、external はモデリングツールからインポート、draft は生成されたもの)、measures(そのテーブルで確認された集計。best_match: true は質問に最も近いものを示します)、joins(保存済みクエリで結合されているテーブル)、docs(そのテーブルに言及するドキュメント)、anchors(そのテーブルを使用する保存済みパターン)が含まれます。source: "catalog_search (no query evidence)" のテーブルは、名前の一致のみで見つかったものです。
  4. anchors:保存済みクエリパターンの要約です。それぞれに kind(metric、model、tableset のいずれか)、base_table、tier、support、説明が含まれます。生成された(draft)アンカーは実際の運用を示す根拠であり、ルールではありません。
  5. documents:検索呼び出しごとにグループ化された、その他のドキュメントです。それぞれ短い preview として示されます。

各抜粋には [start-end] 形式の文字オフセットと、続きを取得するための grep_documents が記載されています。抜粋だけでは必要な詳細がわからない場合は、URN を指定して grep_documents または get_entities でそのドキュメントを取得してください。カードにすでに表示されている検索呼び出しを再実行してはいけません。カードではテーブルのカタログ検索も行われています。すでに一覧にあるテーブルを search で検索してはいけません。また、ワイルドカードクエリでドメイン、データプロダクト、アンカーを一覧表示してはいけません。完全なドキュメントの取得は最大 3 件までにしてください。カードはすでに大きく、テーブルの選択には通常、抜粋で十分です。根拠に基づくクエリで通常許容される範囲は、カード 1 件、inspect_tables_for_sql 呼び出し 1 回、ドキュメントの取得最大 3 件です。追加の呼び出しを行うたびに、回答に必要なコンテキストが消費されます。

2. テーブルを選択する

回答に必要なテーブルをすべて挙げ、それぞれが取得済みのエビデンス(カード文書、candidate_tables、アンカー、またはカタログ検索)に記載されていることを確認します。どれにも記載されていないテーブルは未検証です。列を推測して作り出さず、その旨を伝えてください。

  • リダイレクトに従います。 文書で、クエリ対象の概念には別のテーブルを優先するよう示されている場合は、そのテーブルを主な候補として使い、そちらの文書も読みます。ルーティングに関する助言は既定の経路を示しますが、質問で明示された要件(鮮度、指定されたテーブル、優先テーブルでは対応できない粒度)に優先するものではありません。質問によって別のテーブルを使わざるを得ない場合は、その旨と理由を述べてください。
  • 要求された粒度で、ガバナンス対象のテーブルを使います。 文書化されたテーブルが、要求された指標を要求された粒度で既に提供している場合は、より細かい粒度のテーブルから再構成せず、そのテーブルのネイティブ列を使います。
  • 正規ソースの選択は、質問の粒度で決めます。 どちらも正規とされるキュレーション済み文書が2つある場合は、記載された粒度が質問で求められる粒度と一致する文書を優先します。要求された粒度に一致する文書がない場合に限り、より細かい粒度のテーブルから集計し、その旨を伝えてください。
  • リテラル値は保存済みクエリではなく、質問から取得します。 保存済みクエリやノートブック内のリテラルなIDや値は、あるアナリストが便宜上使ったものです。フィルターにその値をコピーしないでください。質問に示された値、またはキュレーション済み文書や宣言済みの値域(セクション3)で確認できる値を使います。
  • 正規の結合を省略して単純化しないでください。 最も近い保存済みパターンのテーブルと結合をチェックリストとして扱い、省略されている結合を削除する前に調べます。あるテーブルが特定の用途では正規であっても、そのテーブルに含まれるすべての列について正規とは限りません。エンティティラベルやライフサイクルフィールドの取得元がエンティティテーブルだとエビデンスで示されている場合、ブリッジテーブルやルックアップテーブルから取得しないでください。
  • ガバナンス対象のデータサーフェスを優先します。 一致するドメインまたはデータプロダクト内にあるテーブルを、同名でその外部にあるテーブルより優先します。
  • 同名の属性より指標テーブルを優先します。 2つの候補に同じ指標名がある場合は、エンティティテーブルの同名属性列よりも専用の指標テーブルまたはファクトテーブルを優先します。それでも優劣がつかない場合は、両方を提示してください。

カードの情報が乏しい場合(権威ある文書がない、またはdraftやカタログ検索の候補しかない場合)、あるいは候補同士が一致しない場合は、選択する前にビジネス上の意味を確認します。質問または文書で言及されているものの、カードでは解決されていない用語について、entity_typeフィルターを指定してsearchを実行し、用語集の用語、ドメイン、またはデータプロダクトを検索します。カードで曖昧なままの候補URNに対してget_entitiesを実行し、説明、オーナーシップ、タグ、用語、テーブルタイプを意図を示す情報として確認します。また、カード呼び出しでカバーされていない観点に限り、質問の指標と粒度を列名のような形式(order_total units_sold per region daily)で表してsearch_documentsを実行し、filter='subtype != "Semantic Anchor"'を指定します。否定フィルターで結果が何も返らない場合は、フィルターなしで再実行し、アンカーの結果は除外します。ビジネス上の定義が見つからない場合は、その不足を明示してユーザーに確認してください。推測した解釈で補わないでください。

カードや文書だけでは列と粒度が明らかにならない場合は、対象を絞ったlist_schema_fields呼び出しで確認します。また、キーが文書に示されていないテーブルを結合する前には、必ず確認してください。結合キーの両側をそれぞれ検証し、未一致の行を落とす可能性がある推測に基づく内部結合は追加しないでください。「すべてのX」を尋ねる質問に、セグメント化された一部のデータだけで回答していないことも確認します。

3. 選択したテーブルに対してinspect_tables_for_sqlを1回呼び出します

SQL を記述する前に、カードまたはカタログに記載された完全なデータセット URN を使って、次の呼び出しを1回行います。 inspect_tables_for_sql(table_urns=[<SQLでSELECT FROMまたはJOINするすべてのテーブル>], question=<ユーザーからの質問全文>) 呼び出し後にドキュメントで新しいテーブルへ誘導された場合は、そのテーブルも調査します。 この呼び出しを省略することは、分析担当者が常に適用するフィルターをクエリが反映できない最も一般的な原因です。レスポンスには次の項目があります。

  • instructions:指定したテーブルの規約です。必ず従ってください。
  • tables[]:既知の規約があるテーブルごとに1つあります。
    • observed_guards:テーブルへのほぼすべてのクエリで分析担当者が適用する述語です(論理削除、最新バージョン、アクティブ状態、テナントスコープ)。それぞれにsupport_pctがあります。質問に適合するものを適用してください。質問またはキュレーション済みドキュメントに別の指示がある場合のみ、省略できます。省略した場合は、どれをなぜ省略したかを明記してください。論理削除、最新バージョン、アクティブ状態のガードを理由なく省くことが、クエリを誤らせる最も一般的な原因です。
    • value_domains:列ごとのdeclared値(テスト、アサーション、許容値に基づく)とobserved値(過去のWHERE句に基づく)です。ここからリテラルを選び、declaredを優先し、型、大文字・小文字、空白を正確に保ってください。observed値はサンプルであり、値の全範囲ではありません。
    • date_shapes:分析担当者がそのテーブルの日付を絞り込む方法です。特定時点またはスナップショットに関する質問に適合する方法を適用してください。
    • curated_documents:組織がこのテーブルについて作成したドキュメントです。質問との関連度順に並び、それぞれchars_totalのうちchars_shown分が抜粋として表示されます。テーブルの粒度、必須フィルター、列の意味について、これらのドキュメントを正としてください。必要なルールの前で抜粋が途切れている場合は、そのURNに対してgrep_documentsを使い、残りを読み取ってください。
  • tables_without_advisory:既知の規約がないテーブルです。これは証拠がないという意味であり、「フィルターが不要」という意味ではありません。list_schema_fieldsを使って、テーブルのライフサイクル列と有効性列を自分で判断してください。
  • worked_example:同じテーブルを対象にした保存済みパターンが、最大1つ含まれます。relevance、tables、レンダリング済みのpatternsが含まれます。これは構築のテンプレートです。コピーするのではなく、粒度とフィルターを質問に合わせて調整し、<value>と<analyst picks: ...>のプレースホルダーを、この質問に適したリテラルに置き換えてください。
  • message:8つを超えるテーブルを渡した場合に表示されます。調査されたのは最初の8つだけです。SQLで使用するテーブルだけを渡してください。

draft_sql_for_tablesツールもある場合、使用する必要はありません。このツールは現在のワークフローより前のものです。上記の証拠に基づいて、自分でSQLを作成してください。

4. 証拠が食い違う場合

情報源には次の優先順位を付けます。

  1. 人間によるガイダンス:authoritative_instructions、curated_documents、およびblessedまたはreviewedアンカー。アンカーは分析担当者が実行した内容から抽出されるため、繰り返された誤りがパターンになることがあります。一方、キュレーション済みドキュメントは、何が正しいかを組織が明示したものです。ドキュメントと生成されたパターンの間で、テーブル、列、結合キー、フィルター、重複排除とフィルタリングの順序、単位のいずれかが異なる場合は、ドキュメントに従ってください。
  2. 生成された証拠:draftアンカー、observed_guards、観測された値のドメインと日付の形状、worked_example。
  3. 物理的な構造についてはカタログを参照します。ドキュメントで指定された列がスキーマにない場合、または定義のフィルターを表現できない場合は、食い違いを明示し、SQLを記述する前に解決してください。黙って一方を選んではいけません。
  4. それらを踏まえたうえで、自分の仮定を明示します。

これは、テーブルの選択だけでなく、パターンの処理方法にも適用されます。ドキュメントで、パターンが導出する値に対するネイティブ列が指定されている場合は、その列を選択してください。処理の順序が指定されている場合は、その順序に従ってください。パターンにない単位や変換が指定されている場合は、それを適用してください。ドキュメントに記載がない場合、COALESCEによるフォールバックやその他の導出を創作してはいけません。NULL 許容のライフサイクルフィールドが状態を示していることがあります。

5. 実行できる場合は読み取り専用クエリでプローブする

このセクションは、SQL 実行ツールを利用できる場合にのみ適用されます。利用できない場合は、候補テーブルのデータプロファイルやサンプルデータについて get_entities を確認してからセクション 6 に進み、プローブで確定できたはずの前提を記録してください。

結果によってテーブル、結合、フィルター、粒度、または時間枠の判断が変わる場合にのみプローブを実行し、メタデータだけで判断できる場合は省略してください。まず、最も低コストな行の形状を調べるプローブから始めます。

SELECT <needed_columns>
FROM <fully_qualified_table>
LIMIT 1

対象フィールドをメタデータから特定できない場合に限り SELECT * を使い、それ以外は既知の列名を指定してください。ほかの最小限のプローブには、フィルターの適用可能性と粒度を調べる COUNT(*) または小規模なグループ別件数、一意性を調べる COUNT(DISTINCT key) と重複チェック、候補フィールドの NULL 件数または小規模な分布、データの網羅範囲と鮮度を調べるタイムスタンプの MIN と MAX、結合の網羅状況を調べる一致件数と不一致件数があります。必要なフィールドだけを選択し、既知のガード条件を適用して、検証済みのパーティションに絞り込んでください。業務ルールを作り出すためにプローブを使ってはいけません。空の結果、予想外の桁数、エラー、タイムアウトは、アクセス権、鮮度、スキーマのドリフト、またはテーブルの適合性に関する証拠として扱ってください。

信頼できるコンテキストとデータが食い違う場合(定義のフィルターで結果が得られない、指定された列がないか挙動が異なる、回答に定義でカバーされていない前提が必要など)は、差異の特徴を把握する目的に限ってプローブを行い、最終クエリを作成する前に止めてください。定義を引用し、ドリフトの内容を一文で示し、平易な表現で解釈を二つか三つ提示して、ユーザーの意図に合うものを確認してください。診断ラウンドは最大三回とし、各回で新しい仮説を検証してください。

6. SQL を作成して検証する

証拠に基づいて、自分で SQL を作成してください。適合するものがあれば worked_example または最も近い保存済みパターンを出発点とし、この質問の粒度、フィルター、出力に合わせて書き直してください。返す前に、次の項目をすべて確認してください。

  • SQL が読み取るすべてのテーブルをセクション 3 で確認し、引用していること。
  • すべての述語が、質問、キュレーション済みドキュメント、観測されたガード条件または日付の形状、検証済みの結合、または報告するプローブ結果に根拠を持つこと。パターンやドキュメントで適用されているすべてのガード条件が同じ範囲で引き継がれていること。省略する場合は理由を記録していること。
  • すべてのリテラルが、質問、値のドメイン、またはドキュメントに由来し、保存済みクエリのサンプル値に由来していないこと。
  • すべての結合キーが両側で検証済みであり、各結合が必須の出力列に必要であること。
  • 集計の粒度が質問に合っていること。現在の状態または特定時点についての質問では、最新の有効なスナップショットに絞り込んで一つの結果を返し、トレンドや期間別の内訳は質問で求められた場合にのみ含めること。
  • クエリが、質問に答えるために必要な最小限のものであること。

7. 安全に実行して報告する

読み取り専用の SELECT 文を 1 つだけ実行してください。読み取り専用の CTE も含みます。 DDL、DML、ストアドプロシージャ、副作用のある関数は拒否してください。ユーザーが下書きのみを求めていない限り、最終クエリを実行してください。 ユーザーが 1 行またはサンプルを求めていない限り、探索時の LIMIT 1 を最終クエリに引き継がないでください。 実行に失敗した場合は、次の試行をカタログの根拠またはプローブに基づいて行ってください。 truncated の結果はサンプルとして扱ってください。合計やその他の最終集計は、切り詰められた行からではなく、SQL で計算してください。

次の内容を返してください。

  • 回答、または実行上の制約。
  • 最終 SQL。
  • 回答の根拠としたすべてのソース。それぞれ、ツールが返した URN を使用した Markdown リンク [表示名](urn:li:...) で示してください。SQL が読み取るすべてのテーブルのデータセット URN(urn:li:dataset:...)に加え、根拠とした各キュレーション済みドキュメント、用語集の用語、ドメイン、データプロダクトの URN も含めてください。テーブルについてのドキュメントは、テーブルとは別のエンティティです。両方を引用してください。同じテーブルがモデリングツールのデータセット(たとえば dbt)とウェアハウスのデータセットとして存在する場合、SQL が読み取るのはウェアハウスのテーブルです。モデリング用のコピーしかカードに表示されていない場合は、search でウェアハウスのデータセット URN を調べてください。また、モデリング用のコピーは別の候補として名前を示してください。
  • 判断を変える要因となったプローブの結果。
  • 裏付けとなる証拠なしに使用したテーブル。
  • 仮定、省略したガード、および解決されていない曖昧さ。

事実とドキュメント、事実とカタログのメタデータ、自身の推論を区別してください。推論を事実として示してはいけません。下書きのみのモードでは実行を省略しますが、ソースの報告を含むほかのすべての手順は維持してください。

note_metadata_observation が利用可能な場合は、見つかった不一致や不足(用語集の定義がない、説明が誤っているまたは古い、ドキュメントがスキーマまたはアンカーと矛盾している、列のドキュメントがないなど)を通じて報告してください。これは応答を妨げない、結果を待たずに実行される処理です。

コメント