【发布时间】: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