Sql 我怎样才能阻止我的产后复发性CTE无限循环?
背景 我正在CentOS 7上运行Postgres 11。Sql 我怎样才能阻止我的产后复发性CTE无限循环?,sql,postgresql,common-table-expression,recursive-query,Sql,Postgresql,Common Table Expression,Recursive Query,背景 我正在CentOS 7上运行Postgres 11。 多亏S-Man的回答,我最近在博士后学习了递归CTE的基础知识 问题 在处理一个密切相关的问题(计算捆绑包和组件中销售的零件)并使用此递归CTE时,我遇到了一个问题,查询无限期循环,从未完成 我追踪到relator表中存在非虚假的“自参考”条目,即父项名称和子项名称具有相同值的行 我知道这些是问题的根源,因为当我用测试表和数据重新创建情况时,不希望出现的循环行为发生在这些行存在时,而当这些行不存在或当UNION(不包括重复的返回行)时消
多亏S-Man的回答,我最近在博士后学习了递归CTE的基础知识 问题 在处理一个密切相关的问题(计算捆绑包和组件中销售的零件)并使用此递归CTE时,我遇到了一个问题,查询无限期循环,从未完成 我追踪到
relator
表中存在非虚假的“自参考”条目,即父项名称
和子项名称
具有相同值的行
我知道这些是问题的根源,因为当我用测试表和数据重新创建情况时,不希望出现的循环行为发生在这些行存在时,而当这些行不存在或当UNION
(不包括重复的返回行)时消失在CTE中使用,而不是UNION ALL
我认为数据模型本身可能需要调整,这样就不需要这些“自引用”行,但现在,我需要做的是让这个查询在完成时返回所需的数据并停止循环
我怎样才能达到这个结果?非常感谢所有的指导
表格和测试数据
CREATE TABLE the_schema.names_categories (
id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
created_at TIMESTAMPTZ DEFAULT now(),
thing_name TEXT NOT NULL,
thing_category TEXT NOT NULL
);
CREATE TABLE the_schema.relator (
id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
created_at TIMESTAMPTZ DEFAULT now(),
parent_name TEXT NOT NULL,
child_name TEXT NOT NULL,
child_quantity INTEGER NOT NULL
);
/* NOTE: listing_name below is like an alias of a relator.parent_name as it appears in a catalog,
required to know because it is these listing_names that are reflected by sales.sold_name */
CREATE TABLE the_schema.catalog_listings (
id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
created_at TIMESTAMPTZ DEFAULT now(),
listing_name TEXT NOT NULL,
parent_name TEXT NOT NULL
);
CREATE TABLE the_schema.sales (
id INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
created_at TIMESTAMPTZ DEFAULT now(),
sold_name TEXT NOT NULL,
sold_quantity INTEGER NOT NULL
);
CREATE VIEW the_schema.relationships_with_child_category AS (
SELECT
c.listing_name,
r.parent_name,
r.child_name,
r.child_quantity,
n.thing_category AS child_category
FROM
the_schema.catalog_listings c
INNER JOIN
the_schema.relator r
ON c.parent_name = r.parent_name
INNER JOIN
the_schema.names_categories n
ON r.child_name = n.thing_name
);
INSERT INTO the_schema.names_categories (thing_name, thing_category)
VALUES ('parent1', 'bundle'), ('child1', 'assembly'), ('child2', 'assembly'),('subChild1', 'component'),
('subChild2', 'component'), ('subChild3', 'component');
INSERT INTO the_schema.catalog_listings (listing_name, parent_name)
VALUES ('listing1', 'parent1'), ('parent1', 'child1'), ('parent1','child2'), ('child1', 'child1'), ('child2', 'child2');
INSERT INTO the_schema.catalog_listings (listing_name, parent_name)
VALUES ('parent1', 'child1'), ('parent1','child2');
/* note the two 'self-referential' entries */
INSERT INTO the_schema.relator (parent_name, child_name, child_quantity)
VALUES ('parent1', 'child1', 1),('child1', 'subChild1', 1), ('child1', 'subChild2', 1)
('parent1', 'child2', 1),('child2', 'subChild1', 1), ('child2', 'subChild3', 1), ('child1', 'child1', 1), ('child2', 'child2', 1);
INSERT INTO the_schema.sales (sold_name, sold_quantity)
VALUES ('parent1', 1), ('parent1', 2), ('listing1', 1);
当前查询无限期地循环所需的UNION ALL
WITH RECURSIVE cte AS (
SELECT
s.sold_name,
s.sold_quantity,
r.child_name,
r.child_quantity,
r.child_category as category
FROM
the_schema.sales s
JOIN the_schema.relationships_with_child_category r
ON s.sold_name = r.listing_name
UNION ALL
SELECT
cte.sold_name,
cte.sold_quantity,
r.child_name,
r.child_quantity,
r.child_category
FROM cte
JOIN the_schema.relationships_with_child_category r
ON cte.child_name = r.parent_name
)
SELECT
child_name,
SUM(sold_quantity * child_quantity)
FROM cte
WHERE category = 'component'
GROUP BY child_name
;
只需使用
UNION
而不是UNION ALL
就可以避免无限递归
描述实现:
UNION
(但不是UNION ALL
),放弃重复的行。包括递归查询结果中的所有剩余行,并将它们放置在临时工作表中
UNION
(但不是UNION ALL
),放弃重复的行和重复任何先前结果行的行。包括递归查询结果中的所有剩余行,并将它们放置在临时中间表中
“消除重复项”应该会导致中间表在某个点为空,从而结束迭代。在目录列表中表列表名称和父表名称对于child1和child2 在relator表中,对于child1和child2 这些行正在创建循环递归 只需从两个表中删除这两行:
delete from catalog_listings where id in (4,5)
delete from relator where id in (7,8)
然后,您所需的输出将如下所示:
孩子的名字
总和
子弟2
8.
子弟3
8.
子弟1
16
请查看与子类别表的关系。这些数据有效吗?如何维持这种关系?在列表名称的第四列中,父项名称和子项名称具有相同的值(“child1”)。请查看表目录列表和关系抱歉,我没有仔细阅读您的问题。你已经提到了这个问题。现在,您是否只需要在不删除行的情况下获得此结果?这是正确的,非常感谢您的帮助!
r.parent\u name r.child\u name
做了这个把戏,循环停止了。非常欢迎您。最美好的祝福。