1

假设我有一个表示文档的表,它有一个复合主键:一个 id 和一个版本。一个文档的多个版本可以同时存在于表中。

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

从逻辑上讲,视图包含它定义的所有文档/版本。子视图(具有非空 view.parent_id)包含其父视图中的所有文档/版本,以及本身的任何文档。如果在子视图及其父视图中定义了不同版本的文档,则只有在子视图中指定的该文档的版本应该是可见的。如果在具有 NULL doc_version 的子视图中指定了文档,则该文档应被视为不存在于该子视图中,即使它存在于其父视图中。

我想构建给定 view.id 的 SQL,它将为我提供视图中所有文档及其各自版本的列表,如上述规则所定义(无论它是否是子视图)。我知道这最终可能会导致递归查询,但如果这样可以简化事情,我也愿意接受严格的两级层次结构(换句话说,子视图的 parent_id 总是可以假定为空)。

我需要在 Oracle、DB2 和 SQL Server 中表示这一点。它不需要在所有三个数据库中都是完全相同的查询,尽管那肯定很好。

您将如何编写此查询以使其快速运行?

4

1 回答 1

0

不同的 DBMS 处理递归的方式是完全不同的。这是一个专门针对 SQL Server 的有效查询,不一定很快。(请注意,除非您应用查询提示,否则 sql server 将递归嵌套限制为 100 级):

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

您在问题的末尾提到了速度,但您没有提供任何必要的细节来确定实现速度的最佳方法是什么。在 Sql Server 中使用递归通常效率不高。此外,最有效的方法可能在 DBMS 之间有所不同。对于 Sql Server 2008,查找 HierarchyID 数据类型:http ://www.codeproject.com/Articles/37171/HierarchyID-Data-Type-in​​-SQL-Server-2008

于 2012-09-18T22:40:08.920 回答