2013-12-15 1 views
1

N 부모 - 자식 관계를 위쪽으로 가로 지르도록 재귀 SQL 쿼리를 시도한 것은 이번이 처음이며 어디서부터 시작해야할지 모르겠습니다. 어떤 도움을 주시면 감사하겠습니다.임의의 깊이의 비율을 반환하는 재귀 SELECT?

시나리오는 두 개의 테이블이 있습니다 (raterate_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}에 국한되지 않는,하지만 대신 rate_plan.parent_rate_plan_id 계층 구조의 요금 플랜과 임의의 수의 제휴사로부터 요금을받습니다. 재귀는 rate_plan.parent_rate_plan_id = NULL 일 때 밑바닥이됩니다.

나는 단지 JOIN을 수행 할 것이지만, 두 개가 아닌 N 개의 부모 - 자식 관계를 수용해야합니다.

이것은 PostgreSQL 9.x에 있습니다. 나는과 UNION ALL을 시도했는데, SELECTrate_plan에서 rate에 합류하여 부모별로 필터링하려했지만, 그 구조가 어떻게 작동하는지에 대해 부적절한 이해가 있었기 때문에 어디에도 없었습니다.

+0

나는 무엇을 하려는지 완전히 이해하지 못했습니다. 그러나 CTE의 문서에는 배열을 사용하여 부모 노드의 경로를 만드는 그래프에 대한 예제 쿼리가 있습니다. 당신의 나무에 대해서도 똑같이하십시오. 당신이 원하는 쿼리는 (잘하면) 명백해야합니다. 부모님이 접두어가있는 노드를 포함하는 모든 노드 또는 정확히 찾고있는 노드. –

+0

몇 가지 샘플 데이터 (몇 개의 삽입물)를 준비하고이 sqlfiddle에 입력 할 수 있습니까? http://www.sqlfiddle.com/#!15/89073/1? 그런 다음 SQLFiddne에 대한 링크를 첨부하고이 데이터를 기반으로 요구 사항을 설명하고 예상되는 결과를 표시하십시오. – krokodilko

+0

[Postgres의 주 버전] (http://www.postgresql.org/support/versioning/)에는 점 다음의 첫 번째 숫자가 포함됩니다. 현재 버전은 * 9.3 *입니다. –

답변

2

이것은 당신이 당신의 설명에 따르면, 찾고있는 수 있습니다 : 대신 것과 따기 요금을

가장 별 (LENGTH() -iest 접두사) 속도,하지만 ${user rate plan ID}에 제한되지 않고 있지만, 제휴

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; 

재귀는 즉시 최상위 노드 (parent_rate_plan_id IS NULL가)에 도달 할 때 자동으로 중지됩니다.

모든 계획을 수집 한 후에 rate에 가입하는 것이 더 효과적입니다.

The manual on (recursive) CTEs.

+0

이것은 올바른 생각 인 것 같습니다. 그러나, Postgres는 나를 "WITH cte"로 실행시키지 않을 것이며, 자기 참조라고 불평합니다. 하지만 재연과 함께 실행하면 무한히 반복되는 것처럼 보입니다. –

+0

나는 고쳐졌다. 귀하의 추천을 잘못 구현했습니다. 이것은 실제로 그것을하는 것처럼 보입니다! 고맙습니다. –

+0

@AlexBalashov : 누락 된'RECURSIVE' 조항이 추가되었습니다. –