webForumDet fria alternativet

Hierarki ?

8 svar · 522 visningar · startad av Swey

SweyMedlem sedan apr. 20003 971 inlägg
#1

Nu kommer en lurig fråga.
Hur gör man hieraki i SQL?

Säg att jag har en tabell med två fält. id och ownerid. När en post inte är ägd får den 0 som ownereid.

Hur gör jag för att skapa en tabell där hela hierakin är uppbyggd? Jag vill använda en extra kolumn för vilken position varje post har i hierakin. Den vill jag att SQL ska skapa.

Detta är för komplicerat för mig så jag hoppas någon kan hjälpa till.

Exempeltabell

id, ownerid
1 0
2 1
3 2
4 1
5 1
6 5
7 6

Utskrift
id, ownerid, position
1, 0, 0
2, 1, 1
3, 2, 2
4, 1, 1
5, 1, 1
6, 5, 2
7, 6, 3

När jag skriver ut detta på skärmen ska det se ut så här:
1
    2
        3
    4
    5
        6
            7

Detta måste fungera när tabellen inte är sorterad som den är också.

Någon idé? Själv är jag helt hjärndöd...

------------------
 - Swey
Projekt wF PHP

[Redigerat av Swey den 13 jul 2000]

ZaphodMedlem sedan maj 2000107 inlägg
#2

Om jag har fattat dig rätt så ska du ha en funktion som liknar ett forum, när det har träd hieraki.

Typ:

hejsan!
   |
   -Re: Hejsan!
   | |
   | -Hejdå!
   -Re2: Hejsan!
      |
      - Osv...

Det enklaste sättet jag vet som man kan lösa det på är att köra nestade loopar.
Inte speciellt upphetsande, jag vet, och inte speciellt smidigt.

Alternativt så kanske man skulle kunna lösa det genom att göra en lagrad procedur (eh, stored procedure) som sorterar upp det hela?

Iaf, så här har jag löst det i ett forum som jag gjorde (men som jag ska göra om):

MsgLevel är på vilken "level" meddelandet är på. Är det = 1 så är det en ny tråd.

Vet inte hur självförklarande detta är.
Men du får tänka dig att det är ett forum. Koden är ju ganska rörig också (det är delvis därför jag ska göra om den)

sub step1()
dim sql, rs, rs2, id
SQL = "SELECT posts.id as pid, posts.postdate, posts.replies, posts.topic, users.[e-mail], users.name FROM posts, users WHERE posts.GroupRef = 1 AND posts.MsgRef = 0 AND posts.MsgRef = 0 AND posts.userid = users.id ORDER BY Postdate DESC"
set rs = cn.execute(SQL)
do while not rs.eof%>
<tr>
    <td bgcolor="#B0B0B0"><font size="2">
<a href="default.asp?step=2&pid=<%=rs("pid")%>"><%=rs("topic")%></a> - <%=rs("postdate")%>&nbsp;<%=rs("replies")%> relplies / <a href="mailto:<%=rs("e-mail")%>?SUBJECT=FORUM:<%=rs("topic")%>"><%=rs("name")%></a><br>
</font>
</td>
</tr>
<%
id = rs("pid")
SQL = "SELECT posts.id as pid, posts.msglevel, posts.postdate, posts.replies, posts.topic, users.[e-mail], users.name FROM posts, users WHERE posts.GroupRef = 1 AND posts.Msgref ="&id&" AND posts.userid = users.id"
set rs2 = cn.execute(SQL)
do while not rs2.eof
dim tmp,i
for i = 1 to rs2("MsgLevel")
tmp = tmp & "&nbsp;"
next
%>
<tr>
    <td bgcolor="#D6D6D6"><font size="2">
<%=tmp%><a href="default.asp?step=2&pid=<%=rs("pid")%>#<%=id%>"><%=rs2("topic")%></a> - <%=rs2("postdate")%>&nbsp;<%=rs2("replies")%> relplies / <a href="mailto:<%=rs2("e-mail")%>?SUBJECT=FORUM:<%=rs2("topic")%>"><%=rs2("name")%></a><br>
</font>
</td>
</tr>
<%rs2.movenext
tmp = ""
Loop
rs.movenext
loop%>

------------------
/Magnus aka Zaphod
www.designmodule.com.bi

ZaphodMedlem sedan maj 2000107 inlägg
#3

Nu när jag sitter här och kolla lite mer här på webforum. Så ser jag att du håller på med PHP. Så mitt asp exempel kanske inte säger dig ett jota. :/

Då kan jag tyvärr inte hjälpa dig så mycket.

------------------
/Magnus aka Zaphod
www.designmodule.com.bi

emissionMedlem sedan dec. 19996 721 inlägg
#4

Man bör inte sätta nivån i tabellen. Varje inlägg ska i stället innehålla ID:t på det inlägg som besvarats.

ID, ParentID etc..

SELECT:a ut alla inlägg med ParentID 0 eller NULL. För varje rad i utsökningen söker man ut de inlägg som har det gällande ID:t som ParentID, och för varje sådant blablabla....

Det kan låta processorintensivt, men med en snabb databas, som MySQL, är det inget större problem.

------------------
Gunnar Liljas - webbutvecklare
Leon Reklambyrå AB

[Redigerat av emission den 14 jul 2000]

ZaphodMedlem sedan maj 2000107 inlägg
#5

Det var det kodan jag hade gjorde.
MsgRef är hur många som ligger över den.
Så tex om MsgRef är 3 så blir det 3 x "  "

for i = 1 to rs2("MsgLevel")
tmp = tmp & "&nbsp;&nbsp;"
next

Så att posten läggs olika långt från kanten.

Men sedan så ska det gå att göra detta i en stored procedure. Jag sitter å knåpar på det just nu (till SQL server visserligen, men ändå). Såg något exempel i Books online där de gjorde en temporär tabell där de la in allting sorterat. Fast jag vet inte hur man ska göra för att skicka ut det som ett recordset sedan?
Vet någon så säg gärna!

Behöver jag lägga till att det redan finns en inbyggd funktion som heter MS Data Shape som man kan bygga upp hierarkier med jätte simpelet. :)

------------------
/Magnus aka Zaphod
www.designmodule.com.bi

[Redigerat av Zaphod den 14 jul 2000]

emissionMedlem sedan dec. 19996 721 inlägg
#6

Det var det kodan jag hade gjorde.

Men varför har du då en kolumn med msglevel? Nej, vad jag menar är att man gör en rekursiv sökning.

------------------
Gunnar Liljas - webbutvecklare
Leon Reklambyrå AB

SweyMedlem sedan apr. 20003 971 inlägg
#7

Jag kör PHP med mySQL men kan ASP också. Och när man väl börjat med PHP går man inte tillbaka ;)

En rekursiv sökning är ju inga problem att göra. Men jag tänkte på hur man kunde lösa det utan att göra en SELECT för varja rad.

------------------
 - Swey
Projekt wF PHP

emissionMedlem sedan dec. 19996 721 inlägg
#8

Det går inte, om man inte för in onödig information i databasen. Visst kan man göra rekursiva sökningar direkt i SQL....

SELECT A1.Titel from Meddelanden A1,Meddelanden A2 WHERE A1.ParentID=A2.ID

...men om man t.ex. vill lista alla meddelanden som har meddelandet 345 som rot, så går inte det, om man inte för in ID på rotmeddelandet på varje rad. Problemet är ju att varje rad som returneras måste uppfylla alla villkor i WHERE-satsen.

Därför måste man använda en rekursiva funktioner från applikationen som anropar databasen, eller en stored procedure.

En annan variant är att hämta in alla meddelanden, som ska vara med, till en array, och loopa över den rekursivt.

------------------
Gunnar Liljas - webbutvecklare
Leon Reklambyrå AB

ZaphodMedlem sedan maj 2000107 inlägg
#9

Det var därför jag hade MsgLevel, för att man skulle slippa göra en dynamisk nestad loop som kunde gå igenom alla de där 335 st meddelandena. Utan istället så hade jag MsgLevel som bestämde var de skulle vara i trädet.

Fast just nu sitter jag själv å pular med en stored procedure som ska göra en temporär table där den sätter upp allting som det ska vara. Sedan så loopar man bara igenom den vanligt (fast med MsgLevel fortfarande som bestämmer vilken position som den ska ligga på).

Saken är väl bara den att jag inte vet hur man ska göra för att bestämma vilken select som proceduren ska skicka tillbaka. Så att den inte skickar typ 5 recordset, det vill man ju inte :/. Om det nu ens går att bestämma det?

Är det någon som har ett exempel så får den personen kanon gärna visa den :e

------------------
/Magnus aka Zaphod
www.designmodule.com.bi

133 ms totalt · 3 externa anrop · v20260731065814-full.2b84b982
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
131 ms — hämta tråd, inlägg och bilagor (db)