2010-03-15 4 views
7

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

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

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

Пользователь может искать специфические (т.е. Глазго) или в большей площади (т.е. Шотландия).

Эти два подхода я рассматриваю являются:

  1. держать ноту детей в базу данных для каждой записи (то есть кот 1 будет иметь 2, 3, 4 в своих детей на местах) и запроса в отношении этой записи с SELECT * FROM Jobs WHERE Category IN Areas.childrenField.
  2. Используйте рекурсивную функцию, чтобы найти все результаты, имеющие отношение к выбранной области.

Проблемы я вижу, как из являются:

  1. Холдинговой эти данные в БД будет означать того, чтобы следить за всеми изменениями в структуре.
  2. Рекурсия медленная и неэффективная.

Любые идеи, предложения или рекомендации по наилучшему подходу? Я использую C# ASP.NET с MSSQL 2005 DB.

+0

Вы можете сделать рекурсивные запросы, если ваша структура таблицы поддерживает его: Http: // msdn.microsoft.com/en-us/library/ms186243.aspx – FrustratedWithFormsDesigner

+0

Рассматривали ли вы возможность моделирования своей информации в XML и хранения ее в атрибуте XML (в таблице базы данных), чтобы затем вы могли запросить его с помощью XQuery? – XpiritO

ответ

2

Вот подход я видел использовал:

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

Пример Таблица

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

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

SELECT * FROM Areas Where HierarchyID LIKE 'sl%' 
+0

Интересная техника! – FrustratedWithFormsDesigner

+2

В SQL Server 2008 они представили тип данных HierarchyID для обработки этого подхода: http://msdn.microsoft.com/en-us/magazine/cc794278.aspx –

+0

Этот подход выглядит несколько иначе мой вариант 1 идея. Приятно и просто, однако это будет означать, что каждый раз, когда обновляется эта категория, HeiratchyID необходимо переоценить. – WDuffy

1

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

+0

Он использует MSSQL, а не MySQL. – FrustratedWithFormsDesigner

+0

Этот ответ касается «вложенных наборов» как метода обработки иерархических данных. Он просто связан с хорошим объяснением этого, что происходит на сайте MySQL. В нем нет ничего, что связано с MySQL. – patmortech

2

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

1

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

Таблица =>

Id ParentId Имя

Nice простой таблицы?

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

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

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

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

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

Смежные вопросы