【问题标题】:Recursive CTE in SQLiteSQLite 中的递归 CTE
【发布时间】:2015-10-20 03:16:28
【问题描述】:

我正在尝试学习如何使用 SQL 1999 中引入的公用表表达式来解决一般的物料清单问题。我假设给定以下表格:

create table part(id int, name string, price int)
create table assembly(part_id int, subpart_id int, quantity int)

装配表中的一行表示一个零件包含一个子零件的多个实例,这些实例又可能有自己的子零件,依此类推。装配表表示一个结构,一棵树,以给定的 part_id 作为其根。

我想计算结构中每个部分出现的总次数。

这是我使用公用表表达式的尝试:

WITH RECURSIVE bom(part_id, component_id, total) AS
    (SELECT id, id, 1 FROM part 
        UNION
     SELECT assembly.part_id, bom.component_id, sum(assembly.quantity * bom.total)
     FROM assembly, bom
     WHERE assembly.subpart_id = bom.part_id
     GROUP BY assembly.part_id, bom.component_id)
SELECT component_id, total FROM bom WHERE part_id = root;

在 Mac OS X 10.9.5 上的 SQLite 3.9.1 下,我收到以下错误消息: 错误:第 78 行附近:不支持递归聚合查询

那么,这是 SQLite 限制,还是 SQL 标准限制?

在任何一种情况下,谁能告诉我如何重写此解决方案以在公用表表达式中积累更多信息,然后在使用结果表的查询中执行聚合?

非常感谢, 罗德尼

【问题讨论】:

  • 您的示例使用 sqlite3 为我运行。
  • Postgres 也拒绝这样做。但我认为你的 sum() 首先是错误的。我认为您想要的是一个简单的 bom.total + assembly.quantity (因此将树中的所有数量值相加)。另外,我认为如果您直接在 CTE 内选择根节点会更有效:from part where id = root
  • 我可能没有足够清楚地描述这个问题。如果汽车中出现 4 次车轮,车轮中出现 5 次螺母,那么汽车中应该出现 20 次螺母。所以你需要将数量乘以总数。然后,您需要对所有中间部件求和,例如,车轮和其他包含螺母的子部件。
  • 在这种情况下,您需要在外部查询中进行聚合。
  • 是的,我同意可以通过这种方式解决问题,以克服明显缺乏对递归聚合查询的支持。

标签: sql sqlite aggregate-functions common-table-expression recursive-query


【解决方案1】:

这是一个解决问题的简单方法,将聚合移动到外部查询:

WITH RECURSIVE bom(part_id, component_id, total) AS
    (SELECT id, id, 1 FROM part 
        UNION ALL
     SELECT assembly.part_id, bom.component_id, assembly.quantity * bom.total
     FROM assembly, bom
     WHERE assembly.subpart_id = bom.part_id)
SELECT component_id, SUM(total) FROM bom 
WHERE part_id = root
GROUP BY component_id;

与最初的尝试相比,此解决方案需要更多空间和可能更多时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多