2014-01-29 3 views
0

У меня есть таблица сотен услуг, которые я соскабливаю из стороннего веб-сервиса. У услуг есть несколько миллионов символов, которые я также получаю.Прослеживание иерархии SQL снизу вверх до определенного уровня

Иерархия по существу такова;

root 
|_service1 
| |_service1/sub1* 
| |_service1/sub2 
| |_service1/sub3 
| |_service1/sub4 
| | |_service1/sub4/sub1 
| | |_**service1/sub4/sub1/leaf1** 
| | 
| |_service1/sub5 
| 
|_service2 
    |_service2/sub1 
    |_service2/sub2 
    |_service2/sub3 

Так что я пытаюсь достичь - дается Id на лист, я хочу работать на дерево, пока не найдешь ветвь была IsActive верно, то вернуть это значение.

В этом примере я хочу найти действительную военную службу для листа /service1/sub4/sub1/leaf1, который в данном случае является service1/sub1

До сих пор я использую Common Table Expression для работы с вершины вниз и установите дополнительный столбец ActiveServiceId на листьях, находящихся под этой ветвью; с миллионами символов, которые превращаются в очень длительный процесс.

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

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

UPDATE для дальнейшего объяснения существующего подхода. Если я решил, что service1 станет новой активной услугой - листья под сервисом 1 в каждой дочерней ветви должны пузыриться до обслуживания1, и я сброшу все дочерние ветви, поэтому ни один из них не будет отмечен как активный

+1

Вы рассмотрели использование иерархических типов данных ?: http://technet.microsoft.com/en-us/library/bb677173.aspx – Jayvee

+0

Я только что прочитал эту полезную информацию, но теперь я не знаю, Думаю, что это решит эту проблему. – owen79

ответ

1

Вы можете найти это полезно использовать вложенные наборы для хранения этих данных:

http://en.wikipedia.org/wiki/Nested_set_model

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

Использование данных, хранящихся в вложенных наборах, чтобы ваша проблема будет выглядеть следующим образом:

SELECT s.ID 
FROM TreeTable s 
WHERE s.L = (SELECT Max(t.L) 
      FROM TreeTable t, TreeTable LeafNode 
      WHERE t.isActive = true 
       AND t.L < LeafNode.L 
       AND t.R > LeafNode.R 
       AND LeafNode.ID = ?) 
+0

Это, кажется, имеет смысл, я просто пытаюсь понять, как я собираюсь создавать таблицы для этого и добавлять данные. Кажется, я понимаю суть модели. – owen79

+0

Похоже, что добавлять узлы мне нужно выталкивать вправо и влево по количеству добавленных узлов, это правильное понимание? Любой более удобный способ добавления лотов одновременно? – owen79

+0

Да, это так. Вы увеличиваете право всех высших узлов на размер узла (справа налево от него), который вы добавите в + 1.Таким образом, чтобы добавить новый узел листа к родителю, который имеет L = 6 R = 7 Вы: UPDATE TreeTable SET R = R + 2 WHERE R> = 7 Тогда INSERT INTO TreeTable (L, R) VALUES (7 , 8) –

0

Если у вас есть полный путь, хранящийся в виде строки для каждого узла, вы можете сделать следующее:

SELECT r.ID 
FROM TreeTable r, TreeTable rs 
WHERE rs.ID = ? 
    AND r.Path = Left(rs.path,Len(r.Path)) 
    AND Len(r.Path) = (SELECT Max(Len(t.Path)) 
        FROM TreeTable t, TreeTable s 
        WHERE s.ID = ? 
         AND t.Path = Left(s.path,Len(t.Path)) 
         AND t.isActive = true) 

Ok это не красиво, и я приветствую любые предложения для того, чтобы сделать его более аккуратным, но он должен работать.

+0

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

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