Лучший метод для поиска иерархических данных - PullRequest
7 голосов
/ 15 марта 2010

Я смотрю на создание объекта, который позволяет запрашивать данные с иерархической фильтрацией. У меня есть несколько идей, как мне это сделать, но мне было интересно, есть ли какие-либо рекомендации или предложения, которые могут быть более эффективными.

В качестве примера представьте, что пользователь ищет работу. Рабочие зоны будут следующими:

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.

Ответы [ 5 ]

3 голосов
/ 15 марта 2010

Вот подход, который я видел:

Создайте поле типа varchar (max) под названиемierarchyid. Генерация базовых идентификаторов для всех корневых объектов. Для каждого дочернего объекта создайте идентификатор и добавьте к нему идентификаторы родителя (ей).

Пример таблицы

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

Пример запроса

SELECT * FROM Areas Where HierarchyID LIKE 'sl%'
2 голосов
/ 15 марта 2010

Вы можете использовать Общие табличные выражения для выполнения рекурсивных запросов. Я считаю эту технику очень мощной, легкой для чтения и легкой в ​​обслуживании.

2 голосов
/ 15 марта 2010

Вы должны использовать вложенные множества. Вот реализация в MySQL. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

1 голос
/ 15 марта 2010

Как насчет этого?

Таблица =>

Id ParentId Имя

Хороший простой стол?

Тогда как насчет какой-нибудь хорошей сложной части SQL? (CTEs рок, я думаю)

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

Может быть, то, что вы ищете?

0 голосов
/ 18 марта 2010

Я использую древовидную модель Джо Селко для иерархии налога с продаж (штат / округ / город / разное) в нашем приложении, и она работает хорошо.

Ваш запрос "найти работу в этой области или ниже" будет выглядеть примерно так:

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

...