2012-08-01 4 views
1

T-SQL дерево поискT-SQL дерево поиск Выберите из множества узлов, если они находятся под родителем

Выберите из множества узлов, если они находятся под родителем

У меня есть очень большое дерево в записи MSSQL Db (80000+). Мой клиент запросил быстрый поиск дерева с помощью команды LIKE. Команда LIKE возвращает < 500 записей.

Есть ли какая-нибудь рекурсивная команда, которая будет проверять дерево каждого из них быстро, чтобы увидеть, находятся ли они под определенным узлом?

Edit: Я думал, что это было довольно ясно, однако ....

Я на SQL Server 2005.

Table Schema 
- (pK) Id 
- (fK) ParentId 
- FirstName 
- LastName 

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

+1

Пожалуйста, покажите нам свою схему таблицы, какой движок базы данных и версию вы используете (DB2, SQL Server?). Как бы то ни было, ваш вопрос может быть закрыт как «Не настоящий вопрос» – Lamak

ответ

2

Вы можете сделать это с помощью рекурсивного CTE - вам нужен пример кода?

Как это (этот код был протестирован)

WITH recurseTree AS 
(
    SELECT * 
    FROM tableName 
    WHERE Id = @parentID 
    UNION ALL 
    SELECT c.* 
    FROM tableName c 
    JOIN recurseTree p ON c.parentID = p.id 
) 
SELECT * 
FROM recurseTree 

Примечание: Другие версии recient (2008+) дают вам специальный тип данных (hierarchyid) для ведения быстрых деревьев обходов. Это, вероятно, лучший способ пойти, все остальное не будет таким быстрым. Обновить!!

+0

Это было бы здорово. Мы пытались написать это, но пока не совсем поняли. –

+0

Вы не можете делать рекурсивные вызовы из подзапроса, по крайней мере, не в SQL Server 2005. Не уверены в более поздних версиях. –

+0

Я говорю о том, что если вы попытаетесь запустить этот запрос, SQL Server даст вам следующую ошибку: «Рекурсивные ссылки не разрешены в подзапросах». –

1

Это должно помочь вам:

;WITH CTE AS 
(
    SELECT Id, ParentId, FirstName, LastName 
    FROM YourTable 
    UNION ALL 
    SELECT B.Id, B.ParentId, B.FirstName, B.LastName 
    FROM CTE A 
    INNER JOIN YourTable B 
    ON A.ParentId = B.Id 
) 
SELECT * 
FROM CTE 
WHERE FirstName LIKE '%something%' 
OPTION(MAXRECURSION 0) 
+0

У меня это есть, но в этом коде медленно, вы собираете несколько тысяч записей (все поддерева под рассматриваемым узлом), а затем фильтруете его. Если мы можем пойти другим путем, определите, какие узлы в наборе находятся под родительским узлом, это может быть намного быстрее. –