Sql 递归选择查询以返回任意深度的速率?

Sql 递归选择查询以返回任意深度的速率?,sql,postgresql,common-table-expression,recursive-query,Sql,Postgresql,Common Table Expression,Recursive Query,这是我第一次尝试递归SQL查询向上遍历N个父子关系,我不知道从哪里开始。任何帮助都将不胜感激 场景是我有两个表-rate和rate\u plan。费率属于应用于用户的费率计划 CREATE TERM rate_plan ( id integer PRIMARY KEY NOT NULL DEFAULT nextval('rate_plan_id'), descr varcha

这是我第一次尝试递归SQL查询向上遍历N个父子关系,我不知道从哪里开始。任何帮助都将不胜感激

场景是我有两个表-
rate
rate\u plan
。费率属于应用于用户的费率计划

CREATE TERM rate_plan (
   id                  integer PRIMARY KEY NOT NULL
                       DEFAULT nextval('rate_plan_id'),

   descr               varchar(64) NOT NULL,

   parent_rate_plan_id integer NOT NULL REFERENCES rate_plan(id)
);

CREATE TABLE rate (
   id                integer PRIMARY KEY NOT NULL
                     DEFAULT nextval('rate_id'),

   prefix            varchar(24) NOT NULL,

   rate_plan_id      integer NOT NULL 
                     REFERENCES rate_plan(id)
);
获取费率的典型查询:

SELECT * FROM rate  
   WHERE (
      rate_plan_id = ${user rate plan ID} 
      AND prefix = ${prefix}
   )
   ORDER BY LENGTH(prefix) ASC;
我想返回最具体的(
LENGTH()
-iest前缀)费率,但不限于
${user rate plan ID}
,而是从
费率计划。父费率计划ID
层次结构中与任何数量的费率计划关联的费率中选择费率。当
rate\u plan.parent\u rate\u plan\u id=NULL
时,递归应该降到最低点

我只想做一个
连接
,但我需要容纳N个父子关系,而不仅仅是两个


这在PostgreSQL 9.x上。我尝试了递归
UNION ALL
,在每个
SELECT
上加入
rate\u计划
rate
,并尝试按父级进行筛选,但由于对这些结构的工作原理理解不足,结果一无所获。

根据您的描述,这可能就是您正在寻找的:

最具体的(
LENGTH()
-iest前缀)速率,但不受限制 到
${user rate plan ID}
,而是从关联的

一旦到达顶部节点(
parent\u rate\u plan\u id为NULL
),递归就会自动停止

收集完所有计划后,加入一次
rate
会更有效


我不完全理解你想做什么。但在CTE上的文档中,有一个图形查询示例,它使用数组构建父节点的路径。对树执行同样的操作:然后(希望)您想要的查询应该是显而易见的,例如,其父节点包含带有前缀的节点的每个节点,或者您正在查找的任何节点。您是否可以准备一些示例数据(一些插入)并将其输入此sqlfiddle:?然后附加到SQLFiddne的链接,请根据这些数据解释您的需求,并显示预期结果。包括点后的第一个数字。目前的版本是9.3。这似乎是正确的想法;然而,博士后不让我把它当作“和cte一起运行”,抱怨它是自我参照的。但当我像递归一样运行它时,它似乎无限递归;我错误地执行了你的建议。这似乎确实做到了!谢谢。@AlexBalashov:添加了缺少的
RECURSIVE
子句。
WITH RECURSIVE cte AS (
   SELECT id, parent_rate_plan_id
   FROM   rate_plan  
   WHERE  id = ${user rate plan ID} 

   UNION ALL
   SELECT rp.id, rp.parent_rate_plan_id
   FROM   cte
   JOIN   rate_plan rp ON rp.id = cte.parent_rate_plan_id
   )
SELECT *
FROM   cte
JOIN   rate r ON r.rate_plan_id = cte.id
ODER   BY length(prefix) DESC
LIMIT  1;