Recursive SELECT query to return rates of arbitrary depth?

烈酒焚心 提交于 2019-12-11 08:14:01

问题


This is my first time attempting a recursive SQL query to traverse N parent-child relationships upward, and I don't know where to start. Any help would be appreciated.

Scenario is that I have two tables - rate and rate_plan. Rates belong to a rate plan which is applied to a user.

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)
);

A typical query to get a rate:

SELECT * FROM rate  
   WHERE (
      rate_plan_id = ${user rate plan ID} 
      AND prefix = ${prefix}
   )
   ORDER BY LENGTH(prefix) ASC;

What I would like is to return the most-specific (LENGTH()-iest prefix) rate, but not being limited to ${user rate plan ID}, but instead picking rates from those affiliated with any number of rate plans in a rate_plan.parent_rate_plan_id hierarchy. The recursion should bottom out when rate_plan.parent_rate_plan_id = NULL.

I would just do a JOIN, but I need to accommodate N parent-child relationships, not just two.

This is on PostgreSQL 9.x. I tried WITH RECURSIVE and UNION ALL, joining rate_plan to rate on every SELECT and trying to filter by parent, but got nowhere, due to an inadequate understanding of how those constructs work.


回答1:


This might be what you are looking for, according to your description:

the most-specific (LENGTH()-iest prefix) rate, but not being limited to ${user rate plan ID}, but instead picking rates from those affiliated

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;

Recursion stops automatically as soon as the top node (parent_rate_plan_id IS NULL) is reached.

It's more effective to join to rate once after you have collected all plans.

The manual on (recursive) CTEs.



来源:https://stackoverflow.com/questions/20593359/recursive-select-query-to-return-rates-of-arbitrary-depth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!