2013-03-27 2 views
1

У меня есть таблица под названием «Сервисы», которая содержит ServiceID, ParentID и описание, где ParentID является идентификатором ServiceID другой записи. Данные настраиваются таким образом, что они образуют иерархию элементов с несколькими уровнями, а элементы «Root» имеют значение ParentID, равное нулю. Как я могу получить запрос с новым полем, показывающим поток всех родителей до корневого родителя для каждой записи. Конечно, корневые элементы будут иметь это поле пустым. Использование автомобилей в качестве примера, я хотел бы иметь такой текст в этом поле для ввода «Х3» и «Пунто» соответственно:Показать единую иерархию отношений в одном поле в MS SQL

Автомобили> Германия> BMW> 4 Wheel Drive> X3

Автомобили> Италия > FIAT> Передний привод> Punto

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

Заранее благодарен!

UPDATE:

Вот что моя таблица выглядит следующим образом:

CREATE TABLE [dbo].[Services](
[ServiceID] [int] IDENTITY(1,1) NOT NULL, 
[ParentID] [int] NULL, 
[ServiceDescription] [nvarchar](250) NULL) 
+2

Вы можете проверить мой ответ на этот http://stackoverflow.com/questions/14241936/how-can-i-generate-a-hierarchy-path-in-sql-that-leads-to-a -given-node/14243624 # 14243624 – EricZ

+0

Мне удалось использовать ваш пример, чтобы получить список путей, но не смог понять, как его интегрировать с моей таблицей, хотя это то, что мне нужно. Что касается обновления, я просто добавил (со структурой таблицы), как бы я использовал ваш пример для получения такой таблицы ?: ServiceID, ParentID, ServiceDescription, Path – Osprey

+1

Пример @EricZ для одной записи. Ответ, который я дал ниже, является той же рекурсивной логикой, но используется для построения путей для всех записей в таблице. –

ответ

1

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

If  Object_ID('dbo.Services') Is Not Null Drop Table [dbo].[Services]; 
Create Table [dbo].[Services] (ServiceID Int Identity(1,1) NOT NULL, ParenServiceID Int NULL, ServiceDescription Nvarchar(250) NULL); 

Insert [dbo].[Services] 
Select null, 'Automobiles' 
Union All 
Select 1, 'Germany' 
Union All 
Select 2, 'BMW' 
Union All 
Select 3, '4 Wheel Drive' 
Union All 
Select 1, 'Italy' 
Union All 
Select 5, 'FIAT' 
Union All 
Select 4, 'X3' 
Union All 
Select 6, 'Front Wheel Drive' 
Union All 
Select 8, 'Punto'; 

With recurCTE As 
(
     Select h.ServiceID, h2.ParenServiceID As nextParent, Convert(Varchar(max),Isnull(h2.ServiceDescription + ' > ','') + h.ServiceDescription) As Hierarchy 
     From [dbo].[Services] h 
     Left Join [dbo].[Services] h2 
       On h.ParenServiceID = h2.ServiceID 
     Union All 
     Select rc.ServiceID, h.ParenServiceID As nextParent, Convert(Varchar(max),Isnull(h.ServiceDescription + ' > ','') + rc.Hierarchy) As Hierarchy 
     From recurCTE rc 
     Join [dbo].[Services] h 
       On rc.nextParent = h.ServiceID 
),  orderedResults As 
(
     Select ServiceID, Hierarchy 
     From (Select Row_Number() Over (Partition By ServiceID Order By Len(Hierarchy) Desc) As lenPriID, 
         ServiceID, 
         Hierarchy 
       From recurCTE) As n 
     Where lenPriID = 1 
) 
Select h.*, o.Hierarchy 
From orderedResults o 
Join [dbo].[Services] h 
     On o.ServiceID = h.ServiceID 
Where ServiceDescription In ('X3','Punto'); 
+0

Спасибо. Ваш пример, кажется, предполагает, что я знаю, что будут вводить родители детей. К сожалению, я не знаю, какие данные будут введены, и я не знаю количество уровней. – Osprey

+0

Нет, это не так, он предполагает отношения между детьми и родителями. Я использовал соглашение об именах, чтобы сделать его очевидным при просмотре результатов, но вы можете изменить их на все, что захотите. Запрос рекурсивно идентифицирует структуру пути для всех значений в таблице. Могут быть 3 уровня или 100 уровней. –

+0

ОК, извините за недоразумение. Понятно, что я понятия не имею, что вы предлагаете, и поэтому не может реализовать его для своего приложения (потому что я не знаю, как это работает). Я не эксперт по SQL. Возможно ли иметь функцию и передать ее значение «ServiceID», и она возвращает значение «Path» для NVARCHAR (500)? Я ссылаюсь на последнее обновление, где я разместил структуру таблицы. – Osprey

0

Я хотел бы использовать левый присоединяется к некоторому разумному пределу (например, 20), а затем concatatinate строки:

declare @services table (ServiceID int , ParentID int,[Description] varchar(20)) 

insert @services 
select 1,null,'automobiles' union 
select 2,null,'hotels' union 
select 3,1,'Germany' union 
select 4,3,'BMW' union 
select 5,3,'Audi' union 
select 6,2,'Hawaii' union 
select 7,2,'Australia' 

select 

s.Description+'>'+s2.Description+'>'+isnull(s3.Description,'')+'>'+isnull(s4.Description,'') 
from @services s 
left join @services s2 on (s2.ParentID=s.ServiceID) 
left join @services s3 on (s3.ParentID=s2.ServiceID) 
left join @services s4 on (s4.ParentID=s3.ServiceID) 
left join @services s5 on (s5.ParentID=s4.ServiceID) 
+0

Спасибо. Но, как я объяснил Love2Learn, ваш пример, кажется, предполагает, что я знаю, что будут вводить дети и родители. К сожалению, у меня нет этой информации, и я не знаю количества уровней, и поэтому мне нужен рекурсивный подход, как тот, который упоминается EricZ. – Osprey

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