搜索分层数据的最佳方法

时间:2010-03-15 14:27:25

标签: c# asp.net sql-server-2005 recursive-query

我正在寻找建立一个允许使用分层过滤查询数据的工具。我有一些想法,我将如何去做,但想知道是否有任何建议或建议可能更有效。

例如,假设用户正在搜索作业。工作领域如下。

1: Scotland
2: --- West Central
3: ------ Glasgow
4: ------ Etc
5: --- North East
6: ------ Ayrshire
7: ------ Etc

用户可以搜索特定的(即格拉斯哥)或更大的区域(即苏格兰)。

我正在考虑的两种方法是:

  1. 在数据库中记下每个记录中的子项(即cat 1在其子字段中将包含2,3,4),并使用SELECT * FROM Jobs WHERE Category IN Areas.childrenField查询该记录。
  2. 使用递归函数查找与所选区域有关系的所有结果。
  3. 我从两者看到的问题是:

    1. 在数据库中保存此数据意味着必须跟踪结构的所有更改。
    2. 递归缓慢且无效。
    3. 关于最佳方法的任何想法,建议或建议?我正在使用C#ASP.NET和MSSQL 2005 DB。

5 个答案:

答案 0 :(得分:3)

这是我见过的一种方法:

创建名为hierarchyid的varchar(max)字段。 为所有根对象生成基本ID。 对于每个子对象,生成一个id,并在父ID之前加上它。

示例表

ID(PK) HierarchyID Area
1       sl           Scotland 
2       slwc        West Central
3       slwcgg       Glasgow 

示例查询

SELECT * FROM Areas Where HierarchyID LIKE 'sl%'

答案 1 :(得分:2)

您应该使用嵌套集。这是MySQL中的一个实现。 http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

答案 2 :(得分:2)

您可以使用Common Table Expressions进行递归查询。我发现这种技术非常强大,易于阅读和易于维护。

答案 3 :(得分:1)

这个怎么样?

表=>

标识 的ParentId 名称

漂亮简单的桌子?

那么一些不错的复杂片段如何与SQL一起去? (我认为CTE摇滚)

public object FetchCategoryTree()
{
    var sql = @"SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

    WITH AreaTree (ID, Name, ParentID, OrgLevel, SortKey) AS
    (
        -- Create the anchor query. This establishes the starting
        -- point
        SELECT
            a.ID,
            cast('---- ' + a.Name as varchar(255)),
            a.ParentID,
            cast('----' as varchar(55)),
            CAST(a.ID AS VARBINARY(900))
        FROM dbo.Area a
        WHERE a.ParentID is null
        UNION ALL
        -- Create the recursive query. This query will be executed
        -- until it returns no more rows
        SELECT
            a.ID,
            cast('----' + b.OrgLevel + '  ' + a.Name as varchar(255)),
            a.ParentID,
            cast(b.OrgLevel+ '----' as varchar(55)),
            CAST(b.SortKey + CAST (a.ID AS BINARY(4)) AS VARBINARY(900))
        FROM dbo.Area a
                INNER JOIN AreaTree b ON a.ParentID = b.ID
    )
    SELECT * FROM AreaTree
    ORDER BY SortKey";

    return FetchObject(sql);
}

现在这会做一些不太确定的SQL魔术。然而,在外行人的术语中,它基本上将第一部分作为根查询。然后它返回到表并使用第一部分通过连接的答案执行第二部分,并继续执行仍然无法找到更多匹配,基本上是一个大循环。它也很快。

你会得到一堆附有排序键的行。通过排序键订购查询后,您将得到如下答案:

 ---- parent 1
 -------- child 1
 -------- child 2
 ------------ child 2.1
 ---- parent 2
 -------- etc

你可能正在寻找什么?

答案 4 :(得分:0)

我在我们的应用程序中使用Joe Celko的树模型作为销售税层次结构(州/县/市/ misc)并且运行良好。

您的“在此区域或以下找工作”查询看起来像这样:

SELECT * FROM Jobs WHERE Jobs.AreaID IN
(SELECT P1.AreaID
FROM Areas AS P1, Areas AS P2
WHERE P1.lft BETWEEN P2.lft AND P2.rgt
AND P2.Areas.AreaID = @selectedAreaID)

Celko Tree in SQL article