2012-09-18 5 views
1

문서를 나타내는 테이블에 복합 기본 키인 ID와 버전이 있다고 가정 해 보겠습니다. 여러 버전의 문서가 동시에 테이블에 존재할 수 있습니다.오버라이드가있는 다중 SQL 조인

create table document (id bigint not null, version int not null, 
    data varchar(255), primary key(id, version)); 

다른 계층 구조의보기가 있습니다. (이 예제에서는 외래 키와 다른 제약 조건을 사용하지 않지만 적용 할 것입니다.)

create table view (id bigint primary key, parent_id bigint); 

그리고 뷰와 문서 집합을 관련시키는 행을 포함하는 다른 테이블. view_doc.view_id 및 view_doc.doc_id에 고유 한 제한 조건이있어 주어진 문서가 주어진보기에서 두 번 이상 나타나지 않을 수도 있다고 가정합니다.

create table view_doc (id bigint primary key, view_id bigint not null, 
    doc_id bigint not null, doc_version int); 

논리적으로 뷰에는 정의 된 모든 문서/버전이 포함됩니다. 아이 뷰 (null가 아닌 view.parent_id를 가짐)에는 부모에있는 모든 문서/버전과 그 안에있는 모든 문서가 포함됩니다. 하위 버전과 상위 버전에서 서로 다른 버전의 문서가 정의 된 경우 하위 뷰에 지정된 해당 버전의 문서 만 표시되어야합니다. 문서가 NULL doc_version이있는 하위보기에 지정된 경우 문서는 해당 하위보기에 존재하지 않는 것으로 간주되어야합니다 (상위에있는 경우에도 해당).

주어진 view.id에서 위의 규칙에 의해 정의 된대로보기에서 모든 문서와 해당 버전의 목록을 제공하는 SQL을 작성하고 싶습니다 (하위보기인지 여부에 관계 없음) . 이것은 궁극적으로 재귀 쿼리가 될 수 있지만 엄격한 2 수준 계층 구조를 받아 들일 수 있다는 것을 알고 있습니다 (즉, 자식 뷰의 parent_id는 항상 null로 가정 할 수 있습니다).

Oracle, DB2 및 SQL Server에서이를 나타낼 필요가 있습니다. 세 데이터베이스 모두에서 정확히 동일한 쿼리 일 필요는 없지만 확실히 좋을 것입니다.

신속하게 실행되도록이 쿼리를 작성 하시겠습니까?

+0

글쎄, 지금까지 시도한 것은 무엇입니까? 샘플 데이터/결과를 얻을 수 있습니까? 필자가 아는 한, 같은 구조를 많이 공유 할지라도, 목록에있는 RDBMS에서 동일 할 수는 없다 (오라클은 'BIGINT'를 가지고 있지는 않지만, 등가물을 구성 할 수는 없다). –

+0

당신은 당신이 원하는 것을 알 것 같지 않습니다. 예를 들어 뷰의 전체 계층 구조를 원하거나 그렇지 않습니까? 완전히 이식성이 있거나없는 쿼리/데이터베이스 구조를 원하십니까? 얼마나 빨리 쿼리를 실행해야합니까? 얼마나 많은 레코드를 가지게 될 것입니까? (실제로 20 억 개 이상의 문서가 있습니다.) 이러한 제약 조건은 어느 정도 상호 배타적이거나 적어도 상충 관계가 있습니다. –

답변

0

다른 DBMS가 재귀를 처리하는 방식은 상당히 다릅니다. 다음은 SQL 서버 전용 쿼리이며 반드시 빠르지는 않습니다.

--Flatten views 
;with thisView as (
    select ID, 0 as nestingLevel, parent_ID 
    from #view 
    where id = @viewID 
union all 
    select v.ID, tv.nestingLevel + 1 as nestingevel, v.parent_ID 
    from #view v 
     inner join thisView tv on v.ID = tv.parent_id 
),--Determine documents/versions to present 
docSets as (
    select doc_ID, doc_version, ROW_NUMBER() over(partition by doc_id order by nestingLevel) as docSequence 
    from #view_Doc 
     inner join thisView tv on view_id = tv.ID 
)--filter documents 
select * 
from docSets 
where docSequence = 1 
    and doc_version is not null; 

당신은 당신의 질문의 끝에서 속도를 언급하지만, 당신은 무엇을 결정하는 데 필요한 세부 사항 중 하나를 제공하지 않습니다 : (쿼리 힌트를 적용하지 않는 한 100 개 수준으로 중첩하는 SQL 서버 제한 재귀 참고) 속도를 달성하는 가장 좋은 방법은 될 것입니다. 일반적으로 Sql Server에서는 재귀 사용이 효율적이지 않습니다. 또한 DBMS간에 가장 효율적인 접근 방법이 다를 수 있습니다. Sql Server 2008의 경우 HierarchyID 데이터 형식을 찾으십시오. http://www.codeproject.com/Articles/37171/HierarchyID-Data-Type-in-SQL-Server-2008