我有以下查询:
with recursive chain(id, weight, depth) as (
select rpCore.itemID2, rpCore.weight, 1 as depth from relations rpCore where itemID1 = 1048663
union
select r.itemID2, c.weight + r.weight, c.depth + 1from chain c
inner join relations r
on (r.itemID1=id)
where c.depth < 3
order by c.weight + r.weight asc limit 10
) select * from chain order by weight asc limit 10;
如果我运行它,我会收到以下错误:
ERROR: ORDER BY in a recursive query is not implemented
SQL state: 0A000
Character: 313
由于权重的结构方式(所有正面,并且加在一起)如果我可以获得查询的递归部分来排序和限制自身,查询的外部部分将返回我需要的结果,但它似乎您无法在递归查询的递归部分执行订单。
有没有办法模拟这种行为?如果我删除了limit语句,那么查询就会运行,但是由于大量的(由于最终的限制语句而不必要的)行,它运行得非常慢。
答案 0 :(得分:2)
正如我理解你的问题,你想为递归CTE关系添加一个LIMIT,以防止它递归过多的结果,这使查询变慢。
答案是你不能这样做。它不仅没有在PostgreSQL中实现;你所要求的东西在逻辑上是不可能的。
当PostgreSQL对每组相关记录进行递归时,它会累积一个事实上按深度排序的集合。这与您想要的顺序不同,这是一个不相关的列,&#34; weight&#34;。出于这个原因,Postgres没有办法根据权重限制而不累积完整的递归数据集 first 。因此,即使支持CTE中的ORDER BY语句,也不会改善您的表现。
我还要指出,在任何 UNION查询中,ORDER BY应用于结果数据集,不到UNION的每个部分。因此,您无法将其应用于&#34;递归部分&#34;。
当然,您可以通过深度来提前终止递归,就像您在此查询中已经完成的那样。将UNION更改为UNION ALL也可以提高性能。
从语法上讲,你可以通过添加第二个CTE来实现你想要的东西:
with recursive chain(id, weight, depth) as (
select rpCore.itemID2, rpCore.weight, 1 as depth
from relations rpCore
where itemID1 = 1048663
union all
select r.itemID2, c.weight + r.weight, c.depth + 1
from chain c
inner join relations r
on (r.itemID1=id)
where c.depth < 3
),
chain_limit as (
SELECT * FROM chain
ORDER BY weight LIMIT 10
)
select * from chain_limit;
然而,这不会帮助您实现绩效目标。