← 返回案例说明

Schema Selection Evaluator

从已合并的 PR #17 到可运行的检索与关系补全实验

固定 top-k = 8;图补全后可超过候选预算,新增字段会计入上下文成本。

使用手工词表、合成数据与固定参考 SQL。这里只验证候选是否足够支持既定查询及其结果,不能解释为 LLM 准确率或生产效果。

方法平均必要列召回平均候选列数完整策略参考 SQL 结果匹配边界状态符合预期
仅候选检索58.2%4.81 / 51 / 51 / 4
检索 + 路径补全86.0%8.44 / 54 / 54 / 4

前四项仅在带目标策略的用例上计算;边界用例单列。英文/中文订单是同一语义的两个输入。

orders_zh

按客户编号汇总下单时间为上海9月1日至7日、排除取消订单的未发金额和件数

联合租户/订单键补全;时间半开区间、取消与粒度

仅候选检索

ready · 6 列

必要列召回 60.0% · 完整策略 否

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.status"
  ],
  "relationships": [],
  "candidate_columns": 6,
  "notes": [],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 0.6,
    "missing_columns": [
      "order_lines.order_id",
      "order_lines.tenant_id",
      "orders.order_id",
      "orders.tenant_id"
    ],
    "relationships_recall": 0.0,
    "missing_relationships": [
      "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
    ],
    "element_recall": 0.6153846153846154,
    "complete": false,
    "extra_columns": []
  },
  "reference_query": {
    "status": "not_run_incomplete_context",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

路径补全后

ready · 10 列

必要列召回 100.0% · 完整策略 是

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.order_id",
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.tenant_id",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.order_id",
    "orders.status",
    "orders.tenant_id"
  ],
  "relationships": [
    "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
  ],
  "candidate_columns": 10,
  "notes": [
    "Added FK endpoints: order_lines.order_id, order_lines.tenant_id, orders.order_id, orders.tenant_id"
  ],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 1.0,
    "missing_columns": [],
    "relationships_recall": 1.0,
    "missing_relationships": [],
    "element_recall": 1.0,
    "complete": true,
    "extra_columns": []
  },
  "reference_query": {
    "status": "matched",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ],
    "actual_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

orders_en

By customer id, sum remaining amount and quantity for order date September 1–7 Shanghai, excluding cancelled orders

同一业务问题的英文词表覆盖

仅候选检索

ready · 6 列

必要列召回 60.0% · 完整策略 否

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.status"
  ],
  "relationships": [],
  "candidate_columns": 6,
  "notes": [],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 0.6,
    "missing_columns": [
      "order_lines.order_id",
      "order_lines.tenant_id",
      "orders.order_id",
      "orders.tenant_id"
    ],
    "relationships_recall": 0.0,
    "missing_relationships": [
      "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
    ],
    "element_recall": 0.6153846153846154,
    "complete": false,
    "extra_columns": []
  },
  "reference_query": {
    "status": "not_run_incomplete_context",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

路径补全后

ready · 10 列

必要列召回 100.0% · 完整策略 是

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.order_id",
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.tenant_id",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.order_id",
    "orders.status",
    "orders.tenant_id"
  ],
  "relationships": [
    "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
  ],
  "candidate_columns": 10,
  "notes": [
    "Added FK endpoints: order_lines.order_id, order_lines.tenant_id, orders.order_id, orders.tenant_id"
  ],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 1.0,
    "missing_columns": [],
    "relationships_recall": 1.0,
    "missing_relationships": [],
    "element_recall": 1.0,
    "complete": true,
    "extra_columns": []
  },
  "reference_query": {
    "status": "matched",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ],
    "actual_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

customer_product

按客户名称和商品名称汇总下单时间为上海9月1日至7日、排除取消的未发金额

沿客户—订单—明细—商品补齐关系与键

仅候选检索

ready · 7 列

必要列召回 41.2% · 完整策略 否

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "customers",
    "order_lines",
    "orders",
    "products"
  ],
  "columns": [
    "customers.name",
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.status",
    "products.name"
  ],
  "relationships": [],
  "candidate_columns": 7,
  "notes": [],
  "coverage": {
    "strategy": "customer-order-line-product",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 0.4117647058823529,
    "missing_columns": [
      "customers.customer_id",
      "customers.tenant_id",
      "order_lines.order_id",
      "order_lines.product_id",
      "order_lines.tenant_id",
      "orders.customer_id",
      "orders.order_id",
      "orders.tenant_id",
      "products.product_id",
      "products.tenant_id"
    ],
    "relationships_recall": 0.0,
    "missing_relationships": [
      "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)",
      "order_lines(tenant_id,product_id)->products(tenant_id,product_id)",
      "orders(tenant_id,customer_id)->customers(tenant_id,customer_id)"
    ],
    "element_recall": 0.4583333333333333,
    "complete": false,
    "extra_columns": []
  },
  "reference_query": {
    "status": "not_run_incomplete_context",
    "expected_rows": [
      [
        "Acme",
        "Bolt",
        7000
      ],
      [
        "Beta",
        "Nut",
        4000
      ]
    ]
  }
}

路径补全后

ready · 17 列

必要列召回 100.0% · 完整策略 是

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "customers",
    "order_lines",
    "orders",
    "products"
  ],
  "columns": [
    "customers.customer_id",
    "customers.name",
    "customers.tenant_id",
    "order_lines.order_id",
    "order_lines.ordered_qty",
    "order_lines.product_id",
    "order_lines.shipped_qty",
    "order_lines.tenant_id",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.order_id",
    "orders.status",
    "orders.tenant_id",
    "products.name",
    "products.product_id",
    "products.tenant_id"
  ],
  "relationships": [
    "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)",
    "order_lines(tenant_id,product_id)->products(tenant_id,product_id)",
    "orders(tenant_id,customer_id)->customers(tenant_id,customer_id)"
  ],
  "candidate_columns": 17,
  "notes": [
    "Added FK endpoints: customers.customer_id, customers.tenant_id, order_lines.order_id, order_lines.product_id, order_lines.tenant_id, orders.customer_id, orders.order_id, orders.tenant_id, products.product_id, products.tenant_id"
  ],
  "coverage": {
    "strategy": "customer-order-line-product",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 1.0,
    "missing_columns": [],
    "relationships_recall": 1.0,
    "missing_relationships": [],
    "element_recall": 1.0,
    "complete": true,
    "extra_columns": []
  },
  "reference_query": {
    "status": "matched",
    "expected_rows": [
      [
        "Acme",
        "Bolt",
        7000
      ],
      [
        "Beta",
        "Nut",
        4000
      ]
    ],
    "actual_rows": [
      [
        "Acme",
        "Bolt",
        7000
      ],
      [
        "Beta",
        "Nut",
        4000
      ]
    ]
  }
}

stock

列出商品名称和库存

单表问题不需要路径扩展

仅候选检索

ready · 2 列

必要列召回 100.0% · 完整策略 是

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "products"
  ],
  "columns": [
    "products.available_qty",
    "products.name"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [],
  "coverage": {
    "strategy": "scoped-stock",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 1.0,
    "missing_columns": [],
    "relationships_recall": 1.0,
    "missing_relationships": [],
    "element_recall": 1.0,
    "complete": true,
    "extra_columns": []
  },
  "reference_query": {
    "status": "matched",
    "expected_rows": [
      [
        "Bolt",
        30
      ],
      [
        "Nut",
        40
      ]
    ],
    "actual_rows": [
      [
        "Bolt",
        30
      ],
      [
        "Nut",
        40
      ]
    ]
  }
}

路径补全后

ready · 2 列

必要列召回 100.0% · 完整策略 是

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "products"
  ],
  "columns": [
    "products.available_qty",
    "products.name"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [],
  "coverage": {
    "strategy": "scoped-stock",
    "tables_recall": 1.0,
    "missing_tables": [],
    "columns_recall": 1.0,
    "missing_columns": [],
    "relationships_recall": 1.0,
    "missing_relationships": [],
    "element_recall": 1.0,
    "complete": true,
    "extra_columns": []
  },
  "reference_query": {
    "status": "matched",
    "expected_rows": [
      [
        "Bolt",
        30
      ],
      [
        "Nut",
        40
      ]
    ],
    "actual_rows": [
      [
        "Bolt",
        30
      ],
      [
        "Nut",
        40
      ]
    ]
  }
}

underspecified

未发金额

故意缺少分组/日期/状态描述,图扩展不能补出业务口径

仅候选检索

ready · 3 列

必要列召回 30.0% · 完整策略 否

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents"
  ],
  "relationships": [],
  "candidate_columns": 3,
  "notes": [],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 0.5,
    "missing_tables": [
      "orders"
    ],
    "columns_recall": 0.3,
    "missing_columns": [
      "order_lines.order_id",
      "order_lines.tenant_id",
      "orders.created_at",
      "orders.customer_id",
      "orders.order_id",
      "orders.status",
      "orders.tenant_id"
    ],
    "relationships_recall": 0.0,
    "missing_relationships": [
      "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
    ],
    "element_recall": 0.3076923076923077,
    "complete": false,
    "extra_columns": []
  },
  "reference_query": {
    "status": "not_run_incomplete_context",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

路径补全后

ready · 3 列

必要列召回 30.0% · 完整策略 否

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents"
  ],
  "relationships": [],
  "candidate_columns": 3,
  "notes": [],
  "coverage": {
    "strategy": "aggregate-lines-per-order",
    "tables_recall": 0.5,
    "missing_tables": [
      "orders"
    ],
    "columns_recall": 0.3,
    "missing_columns": [
      "order_lines.order_id",
      "order_lines.tenant_id",
      "orders.created_at",
      "orders.customer_id",
      "orders.order_id",
      "orders.status",
      "orders.tenant_id"
    ],
    "relationships_recall": 0.0,
    "missing_relationships": [
      "order_lines(tenant_id,order_id)->orders(tenant_id,order_id)"
    ],
    "element_recall": 0.3076923076923077,
    "complete": false,
    "extra_columns": []
  },
  "reference_query": {
    "status": "not_run_incomplete_context",
    "expected_rows": [
      [
        "C1",
        2,
        10,
        7000
      ],
      [
        "C2",
        1,
        2,
        4000
      ]
    ]
  }
}

denied_salary

列出员工工资 salary

禁止表在排序前被排除

仅候选检索

no_candidates · 0 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "no_candidates",
  "tables": [],
  "columns": [],
  "relationships": [],
  "candidate_columns": 0,
  "notes": [],
  "status_matches_expectation": true
}

路径补全后

no_candidates · 0 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "no_candidates",
  "tables": [],
  "columns": [],
  "relationships": [],
  "candidate_columns": 0,
  "notes": [],
  "status_matches_expectation": true
}

ambiguous_warehouse

列出物流跟踪号和仓库名称

起始仓与目的仓两条关系需要澄清

仅候选检索

ready · 2 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "shipments",
    "warehouses"
  ],
  "columns": [
    "shipments.tracking_number",
    "warehouses.name"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [],
  "status_matches_expectation": false
}

路径补全后

ambiguous_path · 2 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ambiguous_path",
  "tables": [
    "shipments",
    "warehouses"
  ],
  "columns": [
    "shipments.tracking_number",
    "warehouses.name"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [
    "shipments(tenant_id,origin_id)->warehouses(tenant_id,warehouse_id)",
    "shipments(tenant_id,destination_id)->warehouses(tenant_id,warehouse_id)"
  ],
  "status_matches_expectation": true
}

disconnected_invoice

按客户名称汇总发票金额

没有维护过的关系时不按同名字段猜连接

仅候选检索

ready · 2 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "customers",
    "invoices"
  ],
  "columns": [
    "customers.name",
    "invoices.amount_cents"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [],
  "status_matches_expectation": false
}

路径补全后

no_authorized_path · 2 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "no_authorized_path",
  "tables": [
    "customers",
    "invoices"
  ],
  "columns": [
    "customers.name",
    "invoices.amount_cents"
  ],
  "relationships": [],
  "candidate_columns": 2,
  "notes": [
    "customers → invoices: no approved, authorized path"
  ],
  "status_matches_expectation": true
}

denied_join_key

按客户编号汇总下单时间为上海9月1日至7日、排除取消订单的未发金额和件数

补全不能重新引入被禁止的联合键列

仅候选检索

ready · 6 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "ready",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.status"
  ],
  "relationships": [],
  "candidate_columns": 6,
  "notes": [],
  "status_matches_expectation": false
}

路径补全后

no_authorized_path · 6 列

边界用例:单独验收状态

查看候选、遗漏、路径与 SQL 结果
{
  "status": "no_authorized_path",
  "tables": [
    "order_lines",
    "orders"
  ],
  "columns": [
    "order_lines.ordered_qty",
    "order_lines.shipped_qty",
    "order_lines.unit_price_cents",
    "orders.created_at",
    "orders.customer_id",
    "orders.status"
  ],
  "relationships": [],
  "candidate_columns": 6,
  "notes": [
    "order_lines → orders: no approved, authorized path"
  ],
  "status_matches_expectation": true
}

实验边界

[
  "Hand-authored aliases and fixtures; no model or embedding retrieval, no held-out benchmark.",
  "Fixed reference SQL only: result matches are not generated-SQL accuracy.",
  "Graph expansion checks approved connectivity, not automatic business intent or cardinality inference.",
  "The English and Chinese order cases are two language versions of the same business task.",
  "underspecified uses a known target as a diagnostic; its missing intent cannot be inferred from the question."
]

完整机器可读结果:report.json;复现:python3 evaluate.py --top-k 8