我遇到了Postgres 9.3+的一个问题而且我不知何故被卡住了。我有以下结构:
任务是将特定对象翻译成另一个对象(基本上是回答像#34这样的问题;谁将此发票归属于?")。
对象由ID标识,可能的翻译存储在如下表中:
vagrant=# select * from sys_context_translation; source_context | target_context | sys_service_id ----------------+----------------+---------------- 1 | 2 | 1 3 | 2 | 2 2 | 1 | 1 1 | 4 | 1 4 | 5 | 2 4 | 2 | 3 (6 rows)
如你所见,有一条从3到5的路径,如3 - 2 - 1 - 4 - 5.
我现在需要一个向我显示该路径的查询。 (因此,source_context 3为1行,下一个为2,下一个为1,依此类推......)。我现在有以下查询,但它没有返回所需的结果:
WITH RECURSIVE translation (source_context, target_context, sys_service_id) AS ( SELECT source_context, target_context, sys_service_id FROM sys_context_translation AS s1 WHERE source_context = 3 UNION ALL SELECT s2.source_context, s2.target_context, s2.sys_service_id FROM sys_context_translation AS s2, translation AS t1 WHERE t1.target_context = s2.source_context ) SELECT * FROM translation ;
它确实返回很多,但随后不断返回行。以下示例限制为10行。
source_context | target_context | sys_service_id ----------------+----------------+---------------- 3 | 2 | 2 (good one) 2 | 1 | 1 (good one) 1 | 2 | 1 (not useful) 1 | 4 | 1 (good one) 2 | 1 | 1 (not useful) 4 | 5 | 2 (good one) 4 | 2 | 3 (should have stopped a row before) 1 | 2 | 1 (...) 2 | 1 | 1 1 | 4 | 1 (10 rows)
我非常感谢任何提示。
答案 0 :(得分:1)
您的数据中存在循环(循环依赖关系),因此您的查询无穷无尽。
查询应检查找到的路径是否不包含重复。
您可以通过使用路径数组来实现此目的。
(我跳过sys_service_id
无关紧要)。
with recursive translation (source_context, target_context, path)
as
(
select
source_context,
target_context,
array[source_context, target_context]
from sys_context_translation
where source_context = 3
union all
select
s.source_context,
s.target_context,
path || s.target_context
from sys_context_translation as s
join translation as t
on t.target_context = s.source_context
and s.target_context <> all(t.path)
)
select *
from translation;
source_context | target_context | path
----------------+----------------+-------------
3 | 2 | {3,2}
2 | 1 | {3,2,1}
1 | 4 | {3,2,1,4}
4 | 5 | {3,2,1,4,5}
(4 rows)