7

我正在考虑构建一个允许使用分层过滤查询数据的设施。我有一些想法,但我想知道是否有任何建议或建议可能更有效。

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

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. 使用递归函数查找与所选区域相关的所有结果。

我从两者中看到的问题是:

  1. 将这些数据保存在数据库中意味着必须跟踪结构的所有更改。
  2. 递归缓慢且效率低下。

关于最佳方法的任何想法、建议或建议?我将 C# ASP.NET 与 MSSQL 2005 DB 一起使用。

4

5 回答 5

3

这是我见过的一种方法:

创建一个名为 hierarchyid 的 varchar(max) 字段。为所有根对象生成基本 ID。为每个子对象生成一个 id 并在其前面加上 parent(s) id。

示例表

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

示例查询

SELECT * FROM Areas Where HierarchyID LIKE 'sl%'
于 2010-03-15T14:50:14.170 回答
2

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

于 2010-03-15T14:38:16.623 回答
2

您可以使用公用表表达式进行递归查询。我发现这种技术非常强大,易于阅读且易于维护。

于 2010-03-15T14:48:48.493 回答
1

这个怎么样?

表 =>

Id ParentId 名称

漂亮的简单表?

那么用一些漂亮的复杂的 pf 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

可能是您正在寻找的东西?

于 2010-03-15T15:27:10.077 回答
0

我在我们的应用程序中使用 Joe Celko 的销售税层次结构树模型(州/县/市/杂项),它运行良好。

您的“在该区域或以下区域寻找工作”查询将如下所示:

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)

SQL 文章中的 Celko 树

于 2010-03-17T23:02:08.493 回答