Hierarchischer Baum mit rekursiver CTE

08/02/2010 - 15:17 von Michael Zimmermann | Report spam
Hallo!

Ich versuche gerade, eine Hierarchie mittels CTE/rekursiver
Abfrage als Tree darzustellen. Das Vorgehen ist im MSDN hier
http://msdn.microsoft.com/de-de/lib...86243.aspx
beschrieben.

Leider führt das ganze zu einem falschen Ergebnis; laut
der Erlàuterung im MSDN-Artikel kann es eigentlich auch
gar nicht klappen, da immer ganze Ebenen abgefragt und per
UNION angehàngt werden, ohne Rücksicht darauf, ob unter den
Elementen noch Teilbàume hàngen.

Die Ebenen der Elemente werden zwar richtig bestimmt, die
Reihenfolge, die zusammen mit der Ebene die Verwandschaft
festlegt, stimmt aber nicht, wodurch der Baum unbrauchbar
ist.

Wie bekommt man denn die richtige Reihenfolge?

Gruß
Michael

Version: 2005

Code:
=ALTER PROCEDURE [dbo].[usp_Hierarchie]
AS
BEGIN
SET NOCOUNT ON;

WITH qhrcElemente
(xBezeichnung, xid, xfiParent, xEbene)
AS
(
SELECT
Bezeichnung, id, fiParent, 0
FROM
tdatElemente
WHERE
fiParent Is Null

UNION ALL SELECT
Bezeichnung, id, fiParent, xEbene+1
FROM
tdatElemente AS t
INNER JOIN
qhrcElemente AS h
ON t.fiParent = h.xid
)

SELECT
*,SPACE(2*xEbene) + xBezeichnung AS xBAUM
FROM
qhrcElemente
END
=

Tabelleninhalt:
ID Name Parent
1 A 17
2 B 17
3 Aa 1
4 Ab 1
5 Ac 1
6 Aba 4
7 Abb 4
9 Ca 11
10 Cb 11
11 C 17
12 Cba 10
13 Cbb 10
14 Cbc 10
15 Cbba 13
16 Cbbb 13
17 (Urahn) NULL
18 Ba 2
=

Falsche Ausgabe der SP:
Name ID Parent Ebene Baum
(Urahn) 17 NULL 0 (Urahn)
A 1 17 1 A
B 2 17 1 B
C 11 17 1 C
Ca 9 11 2 Ca
Cb 10 11 2 Cb
Cba 12 10 3 Cba
Cbb 13 10 3 Cbb
Cbc 14 10 3 Cbc
Cbba 15 13 4 Cbba
Cbbb 16 13 4 Cbbb
Ba 18 2 2 Ba
Aa 3 1 2 Aa
Ab 4 1 2 Ab
Ac 5 1 2 Ac
Aba 6 4 3 Aba
Abb 7 4 3 Abb
=

Erwünschtes Ergebnis:
Name ID Parent Ebene Baum
(Urahn) 17 NULL 0 (Urahn)
A 1 17 1 A
Aa 3 1 2 Aa
Ab 4 1 2 Ab
Aba 6 4 3 Aba
Abb 7 4 3 Abb
Ac 5 1 2 Ac
B 2 17 1 B
Ba 18 2 2 Ba
C 11 17 1 C
Ca 9 11 2 Ca
Cb 10 11 2 Cb
Cba 12 10 3 Cba
Cbb 13 10 3 Cbb
Cbba 15 13 4 Cbba
Cbbb 16 13 4 Cbbb
Cbc 14 10 3 Cbc
=
 

Lesen sie die antworten

#1 Gerald Aichholzer
08/02/2010 - 17:51 | Warnen spam
Hallo Michael,

Michael Zimmermann wrote:

Ich versuche gerade, eine Hierarchie mittels CTE/rekursiver
Abfrage als Tree darzustellen. Das Vorgehen ist im MSDN hier
http://msdn.microsoft.com/de-de/lib...86243.aspx
beschrieben.

Leider führt das ganze zu einem falschen Ergebnis; laut
der Erlàuterung im MSDN-Artikel kann es eigentlich auch
gar nicht klappen, da immer ganze Ebenen abgefragt und per
UNION angehàngt werden, ohne Rücksicht darauf, ob unter den
Elementen noch Teilbàume hàngen.

Die Ebenen der Elemente werden zwar richtig bestimmt, die
Reihenfolge, die zusammen mit der Ebene die Verwandschaft
festlegt, stimmt aber nicht, wodurch der Baum unbrauchbar
ist.

Wie bekommt man denn die richtige Reihenfolge?



folgende unoptimierte Vorgehensweise liefert die richtige
Reihenfolge:

with tdatElemente as (
select 1 as [id], 'A' as Bezeichnung, 17 as fiParent
union all
select 2 as [id], 'B' as Bezeichnung, 17 as fiParent
union all
select 3 as [id], 'Aa' as Bezeichnung, 1 as fiParent
union all
select 4 as [id], 'Ab' as Bezeichnung, 1 as fiParent
union all
select 5 as [id], 'Ac' as Bezeichnung, 1 as fiParent
union all
select 6 as [id], 'Aba' as Bezeichnung, 4 as fiParent
union all
select 7 as [id], 'Abb' as Bezeichnung, 4 as fiParent
union all
select 9 as [id], 'Ca' as Bezeichnung, 11 as fiParent
union all
select 10 as [id], 'Cb' as Bezeichnung, 11 as fiParent
union all
select 11 as [id], 'C' as Bezeichnung, 17 as fiParent
union all
select 12 as [id], 'Cba' as Bezeichnung, 10 as fiParent
union all
select 13 as [id], 'Cbb' as Bezeichnung, 10 as fiParent
union all
select 14 as [id], 'Cbc' as Bezeichnung, 10 as fiParent
union all
select 15 as [id], 'Cbba' as Bezeichnung, 13 as fiParent
union all
select 16 as [id], 'Cbbb' as Bezeichnung, 13 as fiParent
union all
select 17 as [id], '(Urahn)' as Bezeichnung, NULL as fiParent
union all
select 18 as [id], 'Ba' as Bezeichnung, 2 as fiParent
)
,qhrcElemente(xBezeichnung, xid, xfiParent, xEbene, xSort)
AS
(
SELECT
Bezeichnung, id, fiParent, 0,
xSort = cast(Bezeichnung as varchar(50))
FROM
tdatElemente
WHERE
fiParent Is Null
UNION ALL SELECT
t.Bezeichnung, t.id, t.fiParent, h.xEbene+1,
xSort = left(xSort + '|' + t.Bezeichnung, 50)
FROM
tdatElemente AS t
INNER JOIN
qhrcElemente AS h
ON t.fiParent = h.xid
)
SELECT
*,SPACE(2*xEbene) + xBezeichnung AS xBAUM
FROM
qhrcElemente
ORDER BY
xSort

lg
Gerald

Ähnliche fragen