문제

다음과 비슷한 테이블이 있습니다.

CREATE TABLE example (
  id integer primary key,
  name char(200),
  parentid integer,
  value integer);

parentid 필드를 사용하여 데이터를 트리 구조로 정렬할 수 있습니다.

이제 내가 해결할 수 없는 부분이 있습니다.parentid가 주어지면 해당 parentid 아래의 모든 값 필드를 더하고 트리 분기를 반복하는 SQL 문을 작성할 수 있습니까?

업데이트: 저는 posgreSQL을 사용하고 있으므로 멋진 MS-SQL 기능을 사용할 수 없습니다.어쨌든 저는 이것이 일반적인 SQL 질문으로 취급되기를 바랍니다.

그런데 질문을 한 후 15분 이내에 6개의 답변을 얻을 수 있어서 매우 감동받았습니다!스택 오버플로로 이동하세요!

도움이 되었습니까?

해결책

PostgreSQL에서 필요한 작업을 수행하는 방법에는 몇 가지가 있습니다.

이 같은:

create or replace function example_subtree (integer)
returns setof example as
'declare results record;
         child record;
 begin
  select into results * from example where parent_id = $1;
  if found then
    return next results;
    for child in select id from example
                  where parent_id = $1
      loop
        for temp in select * from example_subtree(child.id)
        loop
          return next temp;
        end loop;
      end loop;
  end if;
  return null;
end;' language 'plpgsql';

select sum(value) as value_sum
  from example_subtree(1234);

다른 팁

다음은 공통 테이블 표현식을 사용하는 예제 스크립트입니다.

with recursive sumthis(id, val) as (
    select id, value
    from example
    where id = :selectedid
    union all
    select C.id, C.value
    from sumthis P
    inner join example C on P.id = C.parentid
)
select sum(val) from sumthis

위의 스크립트는 '가상' 테이블을 생성합니다. sumthis 열이 있는 것 id 그리고 val.이는 두 개의 선택 항목이 병합된 결과로 정의됩니다. union all.

첫 번째 select 루트를 얻습니다(where id = :selectedid).

두번째 select 반환할 항목이 없을 때까지 이전 결과의 하위 항목을 반복적으로 따릅니다.

그런 다음 최종 결과를 일반 테이블처럼 처리할 수 있습니다.이 경우 val 열이 합산됩니다.

버전 8.4부터 PostgreSQL은 재귀 쿼리 지원 SQL 표준을 사용하는 공통 테이블 표현식의 경우 WITH 통사론.

모든 ANSI에서 작동하는 휴대용 솔루션을 원하는 경우 SQL-92 RDBMS를 사용하려면 테이블에 새 열을 추가해야 합니다.

Joe Celko는 이 책의 원저자입니다. 중첩 세트 SQL에 계층 구조를 저장하는 방법.당신은 구글 수 있습니다 "중첩 세트" 계층 구조 배경을 좀 더 이해하기 위해서입니다.

아니면 parentid의 이름을 다음으로 바꿀 수도 있습니다. 좌파 그리고 오른쪽.

다음은 Nested Set을 요약하려는 시도입니다. 저는 Joe Celko가 아니기 때문에 매우 부족합니다.SQL은 집합 기반 언어이며 인접 모델(상위 ID 저장)은 계층 구조의 집합 기반 표현이 아닙니다.따라서 인접 스키마를 쿼리하는 순수한 집합 기반 방법은 없습니다.

하지만, 대부분의 주요 플랫폼은 이 정확한 문제를 해결하기 위해 최근 몇 년 동안 확장 기능을 도입했습니다.따라서 누군가 Postgres 관련 솔루션으로 응답하는 경우 반드시 해당 솔루션을 사용하십시오.

재귀 쿼리를 만드는 표준 방법 SQL 재귀적이다 CTE. PostgreSQL 이후 그들을 지원 8.4.

이전 버전에서는 재귀적 집합 반환 함수를 작성할 수 있습니다.

CREATE FUNCTION fn_hierarchy (parent INT)
RETURNS SETOF example
AS
$$
        SELECT  example
        FROM    example
        WHERE   id = $1
        UNION ALL
        SELECT  fn_hierarchy(id)
        FROM    example
        WHERE   parentid = $1
$$
LANGUAGE 'sql';

SELECT  *
FROM    fn_hierarchy(1)

이 문서를 참조하세요:

SQL Server 2005를 사용하는 경우 공통 테이블 표현식을 사용하여 이를 수행할 수 있는 정말 멋진 방법이 있습니다.

임시 테이블을 생성하는 데 필요한 모든 번거로운 작업이 필요 없으며 기본적으로 WITH 및 UNION만으로 모든 작업을 수행할 수 있습니다.

다음은 좋은 튜토리얼입니다:

http://searchwindevelopment.techtarget.com/tip/0,289483,sid8_gci1278207,00.html

사용하다 공통 테이블 표현식.

SQL Server 2005 이상에만 해당됨을 나타낼 수 있습니다. 데일 레이건

여기 기사가 있어요 공통 테이블 표현식 없이 SqlTeam에 의한 재귀 시.

다음 코드는 컴파일되었으며 정상적으로 테스트되었습니다.

create or replace function subtree (bigint)
returns setof example as $$
declare
    results record;
    entry   record;
    recs    record;
begin
    select into results * from example where parent = $1;
    if found then
        for entry in select child from example where parent = $1 and child  parent loop
            for recs in select * from subtree(entry.child) loop
                return next recs;
            end loop;
        end loop;
    end if;
    return next results;
end;
$$ language 'plpgsql';

내 경우에는 노드가 자신을 가리키기 때문에 "child <> parent" 조건이 필요합니다.

재미있게 보내세요 :)

오라클에는 "START WITH"와 "CONNECT BY"가 있습니다.

select 
    lpad(' ',2*(level-1)) || to_char(child) s

from 
    test_connect_by 

start with parent is null
connect by prior child = parent;

http://www.adp-gmbh.ch/ora/sql/connect_by.html

질문에 대한 답변이 아주 잘 되었음에도 불구하고 간단히 말해서, 이것을 다음과 같이 취급한다면 주목해야 합니다.

일반적인 SQL 질문

SQL'99는 사양에서 선형 재귀를 허용하기 때문에 SQL 구현은 매우 간단합니다(비록 표준을 완벽하게 구현하는 RDBMS는 없다고 생각하지만). WITH RECURSIVE 성명.따라서 이론적 관점에서 우리는 지금 당장 이것을 할 수 있습니다.

어떤 예제도 제대로 작동하지 않았으므로 다음과 같이 수정했습니다.

declare
    results record;
    entry   record;
    recs    record;
begin
    for results in select * from project where pid = $1 loop
        return next results;
        for recs in select * from project_subtree(results.id) loop
            return next recs;
        end loop;
    end loop;
    return;
end;

이게 SQL 서버인가요?루프를 통해 결과를 통합하는 TSQL 저장 프로시저를 작성할 수 없습니까?

그래도 이 작업을 수행하는 SQL 전용 방법이 있는지도 궁금합니다.내가 지리 데이터베이스 수업에서 기억하는 부분에는 분명히 그런 내용이 있을 것입니다.

SQL 2008에서는 더 쉽다고 생각합니다. 계층 ID

계층 구조뿐만 아니라 임의의 그래프를 저장해야 하는 경우 Postgres를 옆으로 밀고 다음과 같은 그래프 데이터베이스를 사용해 볼 수 있습니다. 알레그로그래프:

그래프 데이터베이스의 모든 내용은 트리플(소스 노드, 에지, 대상 노드)로 저장되며 그래프 구조를 조작하고 SQL과 같은 언어를 사용하여 쿼리하는 데 대한 최고 수준의 지원을 제공합니다.

Hibernate 또는 Django ORM과 잘 통합되지는 않지만 그래프 구조(Nested Set 모델이 제공하는 것과 같은 계층 구조뿐만 아니라)에 대해 진지하게 생각한다면 확인해 보세요.

또한 Oracle이 마침내 최신 제품에 실제 그래프에 대한 지원을 추가했다고 생각합니다. 하지만 너무 오랜 시간이 걸려서 이 모델을 통해 많은 문제가 발생할 수 있다는 사실에 놀랐습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top