2016-02-26 2 views
1

У меня возникли проблемы с построением запроса для рекурсивного родительского дерева в SQL Server.SQL Server: дерево CTE с приоритетом

Я нашел общее табличное выражение, но я должен рассмотреть еще один параметр (приоритет на каждом уровне), что я не нашел из поиска через Интернет, поэтому структура моей таблицы, как это

id - parentid - proprity 

Например, если у меня есть эти данные:

1 - NULL - 2 
2 - NULL - 1 
3 - 2 - 2 
4 - 3 - 1 
5 - 2 - 0 
6 - 1 - 0 
7 - 2 - 3 

запрос должен возвращать их в правильном порядке:

-2 
--5 
--3 
---4 
--7 
-1 
--6 

Также этот список можно заказать, поэтому, если любой заказ изменен, я должен сбросить приоритет в нужном месте. У любого уже есть решение для этого случая с запросами в SQL Server?

Заранее спасибо

+1

Здесь отличное место для начала. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+0

Просто включите приоритет в ORDER BY. Отправьте свой запрос, и мы можем его отладить. –

ответ

0

Это даст вам заказ, что вам нужно. Лично я бы попытался сделать этот заказ на уровне отображения, но это будет сделано в SQL.

Это зависит от однозначных значений приоритета. Если они могут быть больше, вам нужно будет добавить приоритеты 0s к приоритетам, например: RIGHT('0' + priority, 2).

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

;WITH Hierarchy_CTE AS 
(
    SELECT 
     id, 
     parent_id, 
     CAST([priority] AS VARCHAR(100)) AS priority_string, 
     id AS base, 
     1 AS lvl 
    FROM 
     My_Table 
    WHERE 
     parent_id IS NULL 
    UNION ALL 
    SELECT 
     MT.id, 
     MT.parent_id, 
     CAST(H.priority_string + CAST(MT.priority AS VARCHAR(20)) AS VARCHAR(100)), 
     H.base, 
     H.lvl + 1 
    FROM 
     Hierarchy_CTE H 
    INNER JOIN My_Table MT ON MT.parent_id = H.id 
) 
SELECT 
    id, 
    base, 
    lvl 
FROM 
    Hierarchy_CTE 
ORDER BY 
    priority_string 
+0

Спасибо за ваш ответ, я пробовал ваш запрос, но он не работает должным образом, если у вас более 10 элементов, потому что элементы первого уровня после десятой «относительной» позиции находятся выше, чем они должны. – ms92ita

+0

Я просто запустил запрос с 11 элементами, и он вернул результаты точно так, как ожидалось. Вы имеете в виду приоритет более 10? Как я объяснил в своем ответе, вы должны изменить код, если это так. Если у вас все еще есть проблемы, добавьте дополнительные данные образца и ожидаемый результат на свой вопрос, который приведет к сбою, и я посмотрю на него. –

+0

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

0

кажется, что это решение работает (взято из Тома H ответа):

;WITH Hierarchy_CTE AS 
(
    SELECT 
     id, 
     parent_id, 
     CAST(REPLICATE('0', 10 - LEN(CAST([Order] AS VARCHAR))) + CAST([Order] AS VARCHAR) + '.' + 
    REPLICATE('0', 10 - LEN(CAST(MerchantCategoryId AS VARCHAR))) + CAST(MerchantCategoryId AS VARCHAR) AS VARCHAR(4000)) AS priority_string, 
     id AS base, 
     1 AS lvl 
    FROM 
     My_Table 
    WHERE 
     parent_id IS NULL 
    UNION ALL 
    SELECT 
     MT.id, 
     MT.parent_id, 
     CAST(H.priority_string + '|' + REPLICATE('0', 10 - LEN(CAST(MT.[priority] AS VARCHAR))) + CAST(MT.[priority] AS VARCHAR) + '.' + 
    REPLICATE('0', 10 - LEN(CAST(MT.id AS VARCHAR))) + CAST(MT.id AS VARCHAR) AS VARCHAR(4000)) AS priority_string, 
     H.base, 
     H.lvl + 1 
    FROM 
     Hierarchy_CTE H 
    INNER JOIN My_Table MT ON MT.parent_id = H.id 
) 
SELECT 
    id, 
    base, 
    lvl 
FROM 
    Hierarchy_CTE 
ORDER BY 
    priority_string 

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

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