关于 datahub-sql-workflow
通过组织内的 DataHub 证据指导 SQL 查询的工作流 skill。它引导分析人员查阅文档、表约定、Schema 和已保存查询模式,并优先遵循经过整理的业务指导。
主要功能
- 01查找与问题相关的 SQL 背景
- 02检查选定表的约定
- 03核对 Schema 字段与表粒度
- 04优先采用整理过的业务指导
- 05指导基于证据编写 SQL
适用场景
- 01按文档中的业务规则编写查询
- 02按目标粒度选择表和连接
- 03核验筛选条件与字段含义
- 04解决文档与查询模式间的冲突
MCP 相关
需要使用 DataHub MCP 工具 `find_sql_context` 和 `inspect_tables_for_sql` 收集证据后再编写 SQL。若任一必需工具不可用,工作流要求停止。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ datahub-project/ datahub-skills --skill datahub-sql-workflow安装后在 Claude Code 中输入/datahub-sql-workflow确认已加载。
详细介绍
DataHub SQL 工作流
确保每个查询都有 DataHub 证据作为依据。两种工具可提供这些证据:
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 并阅读完整信息卡
在调用任何其他工具之前,先调用 find_sql_context(question=<用户的完整问题>),即使用户提供了表名或数据集 URN 也一样。按用户原文传入问题;不要缩减为关键词。
信息卡分为五部分。按以下顺序阅读。
authoritative_instructions:由{call, results}组成的分组。每个call都是已运行的search_documents(...)调用,或用户编辑的锚点指令;results是该调用返回的文档,每篇文档均以最匹配问题的摘录形式呈现。这些是贵组织对该问题的原始表述:连接键、最新行规则、必需筛选条件、“不要使用此表”警告。先阅读每个分组,再进行其他操作。authoritative_instructions_note:说明这些分组的构建方式以及如何进一步查找。请遵循其中的说明。candidate_tables:证据所指向的表。每张表包含tier(blessed或reviewed表示经人工验证,external表示从建模工具导入,draft表示生成的)、measures(该表上出现过的聚合;best_match: true表示与问题最接近的聚合)、joins(已保存查询中与该表连接的表)、docs(提及该表的文档)和anchors(使用该表的已保存模式)。带有source: "catalog_search (no query evidence)"的表仅由名称匹配得出。anchors:精简的已保存查询模式,每个都包含kind(metric、model或tableset)、base_table、tier、support和描述。生成的(draft)锚点是实践证据,而非规则。documents:更多文档,按查找到它们的搜索调用分组,每篇均以简短的preview呈现。
每段摘录都包含 [start-end] 字符偏移量和 grep_documents 后续查询方式。如果摘录未提供某项所需细节,请通过其 URN 使用 grep_documents 或 get_entities 获取该文档。不要重新运行信息卡中已经显示的搜索调用。信息卡也已搜索目录中的表:不要对其中已列出的表使用 search,也不要使用通配符查询列出域、数据产品或锚点。完整获取的文档最多为三篇;信息卡已经很长,通常其摘录足以供你选择表。以证据为依据的查询通常只需信息卡、一次 inspect_tables_for_sql 调用和最多三次文档获取;每增加一次调用,都会占用答案所需的上下文。
2. 选择表
列出答案所需的每张表,然后确认每张表都出现在你检索到的证据中:表卡片文档、candidate_tables、锚点或目录查询。若某张表未出现在其中任何一项中,则该表未经验证;请说明这一点,而不是臆造其列。
- 遵循重定向。 当文档指出查询某个概念时应优先使用另一张表,请将该表作为首选候选,并阅读其文档。路由建议说明默认路径;但不会凌驾于问题中的明确要求之上(如时效性、指定表或首选表无法提供的粒度)。当问题要求偏离默认路径时,请说明偏离及原因。
- 使用满足所需粒度的受治理表。 当有文档记录的表已在所需粒度提供所需度量时,请使用其原生列,而不是从更细粒度的表中重建。
- 问题中的粒度决定规范数据源。 当两份精选文档都声称某张表是规范数据源时,应选择声明粒度与问题所需粒度相符的那张表。只有在没有文档匹配所需粒度时,才从更细粒度的表聚合,并说明原因。
- 从问题而非已保存查询中获取字面值。 已保存查询或笔记本中的字面 ID 或值只是某位分析人员的便捷做法;不要将其复制到筛选条件中。使用问题给出的值,或精选文档及已声明的值域(第 3 节)确认的值。
- 不要省略规范联接。 将最接近的已保存模式中的表和联接视为检查清单:删去任何被省略的联接前,先调查原因。一张表可以针对某种用途是规范数据源,却不一定对其包含的每一列都适用;当证据将实体标签或生命周期字段归于实体表时,不要从桥接表或查找表中获取这些字段。
- 优先选择受治理的数据面。 优先使用匹配域或数据产品内的表,而不是它们之外的同名表。
- 度量表优先于同名属性。 当两个候选表包含同名度量时,优先选择专用度量表或事实表,而不是实体表上的同名属性列;如果仍无法确定,则同时展示两者。
当表卡片信息不足(没有权威文档,只有 draft 或目录搜索候选)或候选项相互矛盾时,应先明确业务含义,再做选择:使用带 entity_type 筛选条件的 search,查找问题或文档提及、但表卡片未能明确的术语、域或数据产品;对表卡片中含义不明确的候选 URN 调用 get_entities,读取其描述、所有权、标签、术语和表类型,以此判断意图;仅当表卡片调用未涵盖某个角度时,才调用 search_documents,并围绕问题中的度量和粒度,以列名风格表述(order_total units_sold per region daily),同时使用 filter='subtype != "Semantic Anchor"'。如果否定筛选条件没有返回结果,则不带筛选条件重新运行,并跳过锚点结果。如果不存在业务定义,请说明这一缺口并向用户提问;不要自行推断解释来填补。
当表卡片和文档未明确列或粒度时,使用有针对性的 list_schema_fields 调用确认;在联接文档中未说明键的表之前,也务必进行确认。验证联接键在两侧都存在;不要添加可能导致未匹配行丢失的推测性内联接。确认“所有 X”这类问题不会从细分子集中作答。
3. 对选定的表调用一次 inspect_tables_for_sql
编写 SQL 之前,请在一次调用中执行
inspect_tables_for_sql(table_urns=[<SQL 将从中 SELECT 或 JOIN 的所有表>], question=<用户的完整问题>)
,并使用卡片或目录中的完整数据集 URN。如果文档在调用后引导你转向新表,也要检查该表。
跳过这一步是查询遗漏分析人员始终会应用的筛选条件的最常见原因。响应包含以下部分:
instructions:有关你询问的表的约定。请遵循这些约定。tables[]:每个已知约定的表各一项:observed_guards:分析人员在该表的几乎每个查询中都会应用的谓词(软删除、最新版本、活动状态、租户范围),每项都带有support_pct。应用适用于当前问题的谓词;只有当问题或精选文档另有说明时才跳过某项,并说明跳过了哪项以及原因。悄悄省略软删除、最新版本或活动状态约束,是查询出错的最常见原因。value_domains:每列的declared值(来自测试、断言和接受值)以及observed值(来自以往的WHERE子句)。从这里选取字面值,优先使用declared值,并保持其类型、大小写和空格完全一致。observed值只是样例,并非完整集合。date_shapes:分析人员如何筛选该表的日期。针对某一时间点或快照问题,应用适用的方式。curated_documents:组织编写的、关于该表的文档,按与你的问题的相关性排序;每项包含摘录,以及chars_shown和chars_total。这些文档是有关表粒度、必需筛选条件和列含义的权威依据。如果摘录在你需要的规则之前就被截断,请使用其 URN 调用grep_documents读取剩余内容。
tables_without_advisory:没有已知约定的表。这表示没有相关证据,而不是“无需筛选”:请自行根据list_schema_fields判断表的生命周期和有效性列。worked_example:至多提供一个使用这些相同表的已保存模式,并包含其relevance、tables和渲染后的patterns。这是构造模板:根据问题调整其粒度和筛选条件,而不要直接照搬;并将<value>和<analyst picks: ...>占位符替换为针对当前问题选定的字面值。message:当传入的表超过 8 张时出现;此时只检查了前 8 张表。请只传入 SQL 实际使用的表。
如果还提供了 draft_sql_for_tables 工具,则无需使用它。它早于此工作流;请根据上述证据自行编写 SQL。
4. 证据不一致时
按以下优先级排列证据来源:
- 人工指导:
authoritative_instructions、curated_documents以及blessed或reviewed锚点。锚点是根据分析人员实际执行过的内容提炼而来,因此重复出现的错误也可能成为模式;精选文档则代表组织对正确做法的说明。如果文档与生成的模式在任何要素上不一致(表、列、连接键、筛选条件、去重与筛选的先后顺序、单位),请遵循文档。 - 生成的证据:
draft锚点、observed_guards、观察到的值域和日期形态,以及worked_example。 - 实际数据目录用于确认物理结构。如果文档提到的列在架构中不存在,或定义中的筛选条件无法表达,请先说明分歧并解决,然后再编写 SQL。切勿悄悄择一采用。
- 你自己的假设,并明确将其说明为假设。
这些规则适用于模式的具体做法,而不只是表的选择:如果文档指定了某个原生列来表示模式推导出的值,请选择文档指定的列;如果文档规定了操作顺序,请遵循该顺序;如果文档说明了模式中遗漏的单位或换算方式,请按其执行。文档未说明时,不要自行添加 COALESCE 回退或其他推导;可为空的生命周期字段可能用于表示状态。
5. 在可执行查询时,使用只读查询进行探查
本节仅适用于有 SQL 执行工具的情况。若没有,请通过 get_entities 检查候选表的数据概况或样例数据,然后继续第 6 节,并记录探查本可确认的假设。
仅当探查结果可能改变表、连接、筛选条件、粒度或时间窗口的决策时才运行探查;如果元数据已足以确定,则跳过。先从成本最低的行形状探查开始:
SELECT <needed_columns>
FROM <fully_qualified_table>
LIMIT 1
已知列名时使用指定列;只有在元数据无法识别相关字段时才使用 SELECT *。其他最简探查包括:使用 COUNT(*) 或小规模分组计数检查筛选条件是否适用以及数据粒度;使用 COUNT(DISTINCT key) 和重复项检查验证唯一性;对候选字段统计空值数量或小规模分布;使用 MIN 和 MAX 时间戳检查覆盖范围和新鲜度;统计匹配和未匹配的数量以检查连接覆盖率。仅选择必需字段,应用已知的约束条件,并限定到已验证的分区。绝不要用探查来臆造业务规则。将空结果、意外数量级、错误和超时视为有关访问权限、数据新鲜度、架构漂移或表适用性的证据。
当权威上下文与数据不一致时(定义中的筛选条件无结果、指定列缺失或表现不同,或答案需要定义未涵盖的假设),仅通过探查描述差异,然后在最终查询之前停止:引用定义,用一句话指出漂移,提供两到三种通俗的解释,并询问哪一种符合用户意图。诊断轮次最多三轮,每轮检验一个新的假设。
6. 编写并验证 SQL
根据证据自行编写 SQL。如果 worked_example 或最接近的已保存模式适用,则以其为起点,并根据本问题的粒度、筛选条件和输出进行改写。返回前检查以下每一项:
- SQL 读取的每张表都已在第 3 节检查并注明引用;
- 每个谓词都能追溯到问题、整理过的文档、观察到的约束条件或日期形状、已验证的连接,或将报告的探查结果;模式或文档应用的每个约束条件都在相同范围内保留,或记录省略原因;
- 每个字面值都来自问题、值域或文档,绝不来自已保存查询的示例值;
- 每个连接键都已在两侧验证,并且每个连接都是必需输出列所要求的;
- 聚合粒度符合问题要求:对于当前状态或某个时间点的问题,固定到最新的有效快照并返回一个结果;只有在问题要求趋势或按周期细分时,才提供趋势或按周期细分;
- 查询应尽可能精简,同时能够回答问题。
7. 安全执行并报告
只执行一条只读 SELECT 语句,包括只读 CTE。
拒绝 DDL、DML、存储过程和会产生副作用的函数。除非用户只要求草稿,否则执行最终查询。除非用户要求一行结果或样本,否则不要将探索时使用的 LIMIT 1 带入最终查询。
如果执行失败,下一次尝试应以目录证据或探查结果为依据。
将 truncated 结果视为样本:在 SQL 中计算总数和其他最终聚合值,绝不要根据截断的行计算。
返回:
- 答案或执行限制;
- 最终 SQL;
- 答案所依赖的所有来源,每项都使用工具返回的 URN,作为 Markdown 链接
[显示名称](urn:li:...):SQL 读取的每个表的数据集 URN(urn:li:dataset:...),以及所依赖的每份精选文档、术语表词条、领域或数据产品的 URN。关于某个表的文档与表本身是不同实体;两者都要引用。如果同一张表同时作为建模工具数据集(例如 dbt)和仓库数据集存在,SQL 读取的是仓库表:引用仓库数据集 URN;若卡片只提供了建模副本,则使用search查找仓库数据集 URN,并将建模副本注明为备用来源; - 影响决策的探查结果;
- 使用但缺乏佐证的任何表;
- 假设、跳过的防护措施以及尚未解决的歧义。
区分事实、文档内容、目录元数据和你自己的推断;绝不要将推断说成事实。仅草稿模式下,省略执行,但保留其他所有步骤,包括来源报告。
如果可以使用 note_metadata_observation,请通过它报告发现的差异和缺漏(例如缺失的术语表定义、错误或过时的描述、与架构或锚点矛盾的文档、缺少的列文档)。该操作为即发即弃,不会阻碍回答。