|
| Rekursivt query på træ Fra : Leif Neland |
Dato : 15-01-09 10:21 |
|
Jeg har et traditionelt træ, hvor hver node har et Id og et ParentId
Kan man lave et query, der giver alle undernoderne fra en node og nedad?
Er der et begrænset antal niveauer, kan jeg jo lave
select id from tabel
where id =123
union
select id from tabel
where parentid =123
union
select a.id from tabel a
inner join tabel b on a.parentid=b.id where b.parentid =123
union
select a.id from tabel a
inner join tabel b on a.parentid=b.id
inner join tabel c on b.parentid=c.id
where c.parentid =123
union
select a.id from tabel a
inner join tabel b on a.parentid=b.id
inner join tabel c on b.parentid=c.id
inner join tabel d on c.parentid=d.id
where d.parentid =123
Det må jeg så kunne proppe ind i en stored procedure.
| |
Andreas Plesner Jaco~ (15-01-2009)
| Kommentar Fra : Andreas Plesner Jaco~ |
Dato : 15-01-09 10:31 |
| | |
Stig Johansen (15-01-2009)
| Kommentar Fra : Stig Johansen |
Dato : 15-01-09 12:23 |
|
Leif Neland wrote:
> Jeg har et traditionelt træ, hvor hver node har et Id og et ParentId
Ja, det er den traditionelle problemstilling med styklistenedbrydning.
> Kan man lave et query, der giver alle undernoderne fra en node og nedad?
Ja.
> Er der et begrænset antal niveauer
Du bestemer selv grænsen, dog synes jeg at kunne huske, at MS Access har en
begrænsning på 28 niveauer.
> union
Brug UNION ALL, så du får 'duplicates' med.
> select id from tabel
> where parentid =123
> union
Jeg tror jeg har skrevet det før, men brug lige så mange LEFT OUTER JOINS
som du mener du har brug for af niveauer.
--
Med venlig hilsen
Stig Johansen
| |
Leif Neland (17-01-2009)
| Kommentar Fra : Leif Neland |
Dato : 17-01-09 02:50 |
|
Stig Johansen skrev:
> Leif Neland wrote:
>
>> Jeg har et traditionelt træ, hvor hver node har et Id og et ParentId
>
> Ja, det er den traditionelle problemstilling med styklistenedbrydning.
>
>> Kan man lave et query, der giver alle undernoderne fra en node og nedad?
>
> Ja.
>
>> Er der et begrænset antal niveauer
>
> Du bestemer selv grænsen, dog synes jeg at kunne huske, at MS Access har en
> begrænsning på 28 niveauer.
>
Jeg glemte vist at skrive det er MS Sqlserver v8
Hvordan får jeg lavet noget, der kan bruges i et query?
Select id,navn from træ where id in noder_under(123)
Kan man i øvrigt have tabelnavn som parameter?
Det antages af alle i forskellige tabeller har felterne id og parentid
Så man laver en generisk funktion noder_under(node,tabel)
Leif
| |
Stig Johansen (17-01-2009)
| Kommentar Fra : Stig Johansen |
Dato : 17-01-09 05:51 |
|
Leif Neland wrote:
> Jeg glemte vist at skrive det er MS Sqlserver v8
>
> Hvordan får jeg lavet noget, der kan bruges i et query?
Det ser ud til den understøtter rekursive UDF's.
Det her eksempel qmå være et godt udgangspunkt for forsøg:
< http://weblogs.sqlteam.com/jeffs/archive/2003/11/21/588.aspx>
> Kan man i øvrigt have tabelnavn som parameter?
> Det antages af alle i forskellige tabeller har felterne id og parentid
> Så man laver en generisk funktion noder_under(node,tabel)
Det plejer at blive noget 'hø' (for mig), fordi så skal man bygge SQL'et som
en streng, og EXEC'e det.
EXEC'en bliver udført i en anden context, og jeg har aldrig fået det til at
hænge sammen (bortset fra at bruge temporære tabeller).
--
Med venlig hilsen
Stig Johansen
| |
Leif Neland (27-01-2009)
| Kommentar Fra : Leif Neland |
Dato : 27-01-09 12:49 |
|
Stig Johansen skrev:
> Leif Neland wrote:
>
>> Jeg har et traditionelt træ, hvor hver node har et Id og et ParentId
>
> Ja, det er den traditionelle problemstilling med styklistenedbrydning.
>
>> Kan man lave et query, der giver alle undernoderne fra en node og nedad?
>
> Ja.
>
>> Er der et begrænset antal niveauer
>
> Du bestemer selv grænsen, dog synes jeg at kunne huske, at MS Access har en
> begrænsning på 28 niveauer.
>
>> union
>
> Brug UNION ALL, så du får 'duplicates' med.
>
>> select id from tabel
>> where parentid =123
>> union
>
> Jeg tror jeg har skrevet det før, men brug lige så mange LEFT OUTER JOINS
> som du mener du har brug for af niveauer.
>
Ja, det har du.
"SELECT m.link AS mlink, m1.link AS m1link, m2.link AS m2link ...
FROM menu m
LEFT JOIN menu m1 ON m1.parentid = m.id
LEFT JOIN menu m2 ON m2.parentid = m1.id
..... osv..
WHERE m.parentid=0
ORDER BY m,m1,m2..
"
Det kunne give en række "1,10,37,null,null,null"
Så har jeg brugt coalesce(m4.id,m3.id,m2.id,m1.id) as nodeid til at
finde id'et på den "yderste" node, 37 i dette tilfælde
Er der en smart funktion til at tælle antallet af (non-)nulls i et antal
felter, 3 i dette tilfælde, for at angive niveauet?
Andet end (pseudo)
if m7 is not null then 7 else
if m6 is not null then 6 else
if m5 is not null then 5 else
if m4 is not null then 4 else
if m3 is not null then 3 else
if m2 is not null then 2 else
if m1 is not null then 1 else 0 end if
end if
end if
end if
end if
end if
end if
smart_funktion(1,10,37,null,null,null)=3
| |
Troels Arvin (15-01-2009)
| Kommentar Fra : Troels Arvin |
Dato : 15-01-09 23:14 |
|
Leif Neland wrote:
> Jeg har et traditionelt træ, hvor hver node har et Id og et ParentId
[...]
"De tre store" databaser vil snart alle have understøttelse af rekursiv
SQL, via "common table expressions" (WITH RECURSIVE). DB2 og MSSQL har
allerede, mens Oracle først vil få det i næste opdatering til v. 11g[1];
Oracle har dog allerede længe haft en lidt mindre avanceret rekursions-
facilitet (CONNECT BY). PostgreSQL skulle også gerne snart få
understøttelse af standard rekursiv SQL.
Så: Hvis dit DBMS understøtter standard rekursiv SQL, synes det at være
vejen frem.
Hvis dit DBMS ikke understøtter det, er der alternative muligheder for at
modellere et hierarki. Nogle af disse vil antagelig også slå rekursiv SQL
performance-mæssigt, inden for visse brugs-scenarier. På http://
troels.arvin.dk/db/rdbms/links/#hierarchical har jeg samlet en række gode
links om emnet. Jeg kan anbefale at starte med Vadim Tropashkos oversigt
over mulighederne[2], som sammenfatter, hvornår hvilken model er på sin
plads.
Noter:
1: http://vadimtropashko.wordpress.com/2008/11/18/finally/
2: http://vadimtropashko.wordpress.com/2008/08/09/one-more-nested-
intervals-vs-adjacency-list-comparison/
| |
|
|