2015-11-12 6 views
0

в моей SQL таблицы я следующие данныеSQL-запрос, чтобы получить multihierarchy элементы

ID Level Description  Code MasterID 
1 1  Cars   AD0  NULL 
2 1  Trucks   JF1  NULL 
3 1  Items   YU2  NULL 
4 2  New Cars  AS3  1 
5 2  Used Cars  TG4  1 
6 2  Car parts  UJ5  1 
7 2  New trucks  OL6  2 
8 2  Used trucks  PL7  2 
9 2  Truck parts  KJL8  2 
10 2  Factory stuff UY9  3 
11 2  Custom stuff RT10  3 
12 3  Toyota   6YH11  4 
13 3  BMW    9OKH12  4 
14 3  VW    13   5 
15 3  Tiers Type I J14  6 
16 3  Tiers Type II J15  6 
17 3  Tiers Type III ADS16  9 
18 3  Seats   SA17  6 
19 3  Doors   UU18  6 
20 3  Lights   9OL19  6 
21 4  Left light  GH20  20 
22 4  Right light  H21  20 
23 4  Left door  JHJ22  19 
24 4  Michelin  UY23  16 
25 4  Vredestein  GTF24  17 
26 4  Dunlop   25   15 

Мое достижение, чтобы получить все иерархические данные для каждого отдельного элемента. Для Exmaple, то outpu должен выглядеть следующим образом

ID Level Description Code MasterId1 Description1  MasterId2 Description2 MasterId3 Description3 

24 4  Michelin  UY23  16  Tiers Type II  6   Car Parts   1  Cars 
. 
. 
19 3  Doors  UU18  6  Car Parts   1   Cars    NULL  NULL 
. 
. 
10 2  Factory Stuff UY9  3  Items    NULL  NULL     NULL  NULL 
. 
. 
3 1  Items  NULL  NULL  NULL    NULL  NULL     NULL  NULL 
. 
. 

Если кто-то может помочь или дать совет, как добиться этого?

+1

Можете ли вы показать нам, что вы делали до сих пор? – Marusyk

+0

В общем случае [CTE выполнит трюк в этом сценарии] (http://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example). Я предлагаю вам начать с этого, а также взглянуть на «UNPIVOT», затем на динамический SQL, а затем подумать о том, как объединить их все вместе. Но все это зависит от используемой СУБД. –

+0

есть ли максимальное количество уровней? – JamieD77

ответ

0

Это не динамично, но это может быть довольно легко.

Используя рекурсивный cte, вы можете получить иерархию для всей таблицы и самостоятельно присоединиться несколько раз, чтобы получить нужную структуру таблицы.

;WITH cte AS 
(
    SELECT *, ID AS [RootID], 1 AS [MasterLevel] FROM Table1 
    UNION ALL 
    SELECT t1.*, cte.[RootID], cte.[MasterLevel] + 1 FROM Table1 t1 
    JOIN cte ON t1.ID = cte.MasterID 
) 
SELECT r.ID, r.[Level], r.[Description], r.[Code], 
     m1.ID AS MasterId1, m1.[Description] AS Description1, 
     m2.ID AS MasterId2, m1.[Description] AS Description2, 
     m3.ID AS MasterId3, m1.[Description] AS Description3 
FROM cte r 
     LEFT JOIN cte m1 ON m1.[RootID] = r.[RootID] AND m1.MasterLevel = 2 
     LEFT JOIN cte m2 ON m2.[RootID] = r.[RootID] AND m2.MasterLevel = 3 
     LEFT JOIN cte m3 ON m3.[RootID] = r.[RootID] AND m3.MasterLevel = 4 
WHERE r.MasterLevel = 1 
ORDER BY r.RootID DESC, r.MasterLevel 

Это будет строить динамический SQL, чтобы получить мастер и полей на основе Дайте описание на максимальной Level значения. или вы могли бы определить, сколько уровней вы хотите увидеть, изменяя @MaxLevel

DECLARE @Sql VARCHAR(MAX) = '', 
     @SelectSql VARCHAR(MAX) = '', 
     @JoinSql VARCHAR(MAX) = '', 
     @MaxLevel INT, 
     @idx INT = 1 

SET @MaxLevel = (SELECT MAX([Level]) FROM Table1) 
WHILE @idx < @MaxLevel 
BEGIN 
    SET @SelectSql = @SelectSql + REPLACE(', m<index>.ID AS MasterId<index>, m<index>.[Description] AS Description<index> ', '<index>', @idx) 
    SET @JoinSql = @JoinSql + REPLACE(' LEFT JOIN cte m<index> ON m<index>.[RootID] = r.[RootID] AND m<index>.MasterLevel = <index> ', '<index>', @idx) 
    SET @idx = @idx + 1 
END   
SET @Sql = ' 
    ;WITH cte AS 
    (
     SELECT *, ID AS [RootID], 0 AS [MasterLevel] FROM Table1 
     UNION ALL 
     SELECT t1.*, cte.[RootID], cte.[MasterLevel] + 1 FROM Table1 t1 
     JOIN cte ON t1.ID = cte.MasterID 
    ) 
    SELECT r.ID, r.[Level], r.[Description], r.[Code]' + @SelectSql 
    + 'FROM cte r ' + @JoinSql 
    + 'WHERE r.MasterLevel = 0 
    ORDER BY r.RootID DESC, r.MasterLevel' 

EXEC(@Sql) 
+0

Просто измените m1. [Description] на m1, m2 и m3, и это будет. Thanx ... – digestBen