7

階層フィルタリングを使用してデータをクエリできる機能を構築することを検討しています。私はそれをどのように進めるかについていくつかのアイデアを持っていますが、より効率的かもしれない推奨事項や提案があるかどうか疑問に思っていました。

例として、ユーザーが仕事を探していると想像してください。職種は以下のとおりです。

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

ユーザーは、特定の地域(グラスゴーなど)またはより広い地域(スコットランドなど)で検索できます。

私が検討している2つのアプローチは次のとおりです。

  1. 各レコードのデータベースに子を記録し(つまり、猫1の子フィールドに2、3、4が含まれる)、そのレコードに対して。を使用してクエリを実行しますSELECT * FROM Jobs WHERE Category IN Areas.childrenField
  2. 再帰関数を使用して、選択した領域に関連するすべての結果を検索します。

私が両方から見る問題は次のとおりです。

  1. このデータをデータベースに保持することは、構造に対するすべての変更を追跡する必要があることを意味します。
  2. 再帰は遅く、非効率的です。

最善のアプローチに関するアイデア、提案、または推奨事項はありますか?MSSQL 2005 DBでC#ASP.NETを使用しています。

4

5 に答える 5

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%'
于 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 名前

素敵なシンプルなテーブル?

それなら、それに合わせて 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 マジックが実行されます。ただし、平たく言えば、基本的に最初の部分をルート クエリとして使用します。次に、テーブルに戻り、結合を介して最初の部分の回答を使用して 2 番目の部分を実行し、それ以上の一致を見つけることができず、基本的には大きなループを続けます。それもかなり速いです。

ソートキーが添付された一連の行を取得します。ソートキーでクエリを並べ替えると、次のような答えが得られます。

 ---- 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 に答える