Avatar billede weiland Nybegynder
21. december 2002 - 20:13 Der er 16 kommentarer og
1 løsning

Nestede forespørgsler

Jeg har en tabel med følgende felter:

PageID
Titel
ParentPageID

- det er altå en hierarkisk struktur, hvor sider er knyttet til hinanden.

Men hvordan laver jeg et udtræk af data? Det må være noget med nestede select-forespørgsler, men det er jeg IKKE så god til :-)

1) Hvordan udtrækker jeg en liste over sider, og de sider, der er knyttet til dem?

2) Hvordan forespørger jeg på, til hvilken sider en bestemt side er knyttet?
Avatar billede burningice Nybegynder
21. december 2002 - 22:20 #1
Set RS = Conn.Execute("SELECT PageId, Titel FROM [tabel]")

Do Until RS.EOF
    Response.Write RS("Titel") &"<br>"
    Set Child = Conn.Execute("SELECT Titel FROM [tabel] WHERE PageId = "& RS("PageId"))
    If NOT Child.EOF Or Not Child.BOF Then
      Do Until Child.EOF
          Response.Write "--> " Child("Title") &"<br>"
      Loop
    End If
Loop

Set RS = Nothing
Avatar billede burningice Nybegynder
21. december 2002 - 22:22 #2
det var lige hurtigt skrevet, og er baseret på at dit hireaki er to levels dybt... jeg kan dog godt skrive en metode så det kan gå uendeligt dybt
Avatar billede burningice Nybegynder
21. december 2002 - 22:46 #3
Function GetChilds(Id)
  Set Child = Conn.Execute("SELECT * FROM [table] WHERE ParentId = "& Id)
  If Child.EOF Or Child.BOF
      GetChilds = false
  Else
      Do Until Child.EOF
          GetChilds = GetChilds & Child("Title")
          If NOT GetChilds(Child("ID") = false THen
              GetChilds = GetChilds & GetChilds(Child("PageId"))
          End If
      Loop
  End If
End Function


Set RS = Conn.Execute("SELECT * FROM [table] WHERE PageId = 0")

Do Until RS.EOF
    Response.Write RS("Title") & "<br>"
    Response.Write "-->"& GetChilds(RS("PageId")
Loop

Den skulle gerne få fat i childs til childs til childs... ;)
Avatar billede skg Nybegynder
21. december 2002 - 23:18 #4
pas nu lige på med at glemme de der Rs.Next
Avatar billede burningice Nybegynder
21. december 2002 - 23:48 #5
pis lort prut tis alt muligt ;)

ja, der skal en .Next ind et par steder, og der skal nok rettes lidt i det før det virker... evt. skal der laves en seperation funktion til at finde ud om der er nogle childs til et id, men det er noget i den retning i hvert fald retning...
Avatar billede weiland Nybegynder
22. december 2002 - 11:46 #6
Tak for hjælpen, men jeg kan ikke få det til at virke. Mit første spørgsmål er: hvorfor er det Set RS = Conn.Execute("SELECT * FROM [table] WHERE PageId = 0")?
I min tabel har jeg ingen PageID, som er 0. Feltet er autonummering.

Mit mål er at få en navigationslinie lissom her på eksperten. Altså hvor man kan se, hvor man er henne i systemet.
Og det skal virke, selvom man går direkte ind på sitet via et link, fx. www.site.dk/default.asp?PageID=67.
Avatar billede burningice Nybegynder
22. december 2002 - 11:54 #7
se min kommentar "og der skal nok rettes lidt i det før det virker"... jeg kender ikke din database eller hvordan dine felter er nummererede, og der skulle forresten stå ParentPageId = 0 og ikke PageId ;)... men der må da være en/flere hovedsider som ikke har noget parentpageid... ??

Jeg har ikke i sinde at lave hele koden for dig, det synes jeg personligt ligger uden for eksperten.dk's område, kun komme med forslag til hvordan det skal laves... Hvis du vil have hele koden lavet kan jeg henvise til sharksforum.com, eller freelance-kategorien.
Avatar billede weiland Nybegynder
22. december 2002 - 13:43 #8
Jeg har prøvet mig lidt frem, og nu VIRKER det! Utrolig lækkert...
Jeg har rettet tingene lidt til, men mangler lige at regne ud, hvordan jeg får det til at stå i listeopstilling med indryk. Lige nu ser resultatet 'bare' sådan ud:

Firmaer
Jensen & Søn
Kontaktperson hos Jensen & Søn
Hansen & Søn
Kontaktperson hos Hansen & Søn

Koden ser nu sådan ud:

Function GetChilds(Id)
  Set Child = MyConn.Execute("SELECT * FROM Pages WHERE ParentPageId = "& Id)
  If Child.EOF Or Child.BOF then
      GetChilds = false
  Else
      While not Child.EOF
          GetChilds = GetChilds & Child("Title") & "<br>"
          If not GetChilds(Child("PageId")) = false Then
              GetChilds = GetChilds & GetChilds(Child("PageId")) & "<br>"
          End If
      Child.MoveNext
      wend
  End If
End Function


Set RS = MyConn.Execute("SELECT * FROM Pages WHERE ParentPageId = 0")

While not RS.EOF
    Response.Write "<b>"& RS("Title") &"</b><br>"
    Response.Write ""& GetChilds(RS("PageID"))
rs.MoveNext
wend

- det er ikke HELT gået op for mig, HVORDAN det virker, men det siger jo en del om cyberfessor :-)
Avatar billede burningice Nybegynder
22. december 2002 - 13:56 #9
det med indrykning kan du vist klare ved at rette i denne linje

GetChilds = GetChilds & Child("Title") & "<br>"

Prøv evt
GetChilds = GetChilds & "-->" & Child("Title") & "<br>"


Ang. hvordan det virker kan jeg da godt hurtigt ridset det op

Du starter med at hente alle sider ud som har ParentPageId = 0

Så begynder du at skrive dem ud en efter en, og for hver side tjekker du så om der er nogle childs. Hvis der er det henter du alle childsene og skriver dem ud en efter en. Ikke nok med det tjekker du også for hvert child om der er child til den, osv. osv. Når der så ikke er flere childs kan vi gå videre til næste hovedside, altså side som har ParentPageId = 0, og så tjekke om der er childs til den.
Avatar billede weiland Nybegynder
22. december 2002 - 14:20 #10
Siden her melder fejl, når jeg indsender kommentar. Jeg laver lige en tester.
Avatar billede weiland Nybegynder
22. december 2002 - 14:22 #11
OK, nu går det bedre...

Tak for forklaringen. Jeg har nu prøvet med indryk. Din løsning skelnede ikke mellem de forskellige niveauer af sider, vel?
Derfor har jeg nu tilføjet en ny kolonne i tabellen, som hedder Niveau. Derefter har jeg lavet denne kode:

Function GetChilds(Id)
  Set Child = MyConn.Execute("SELECT * FROM Pages WHERE ParentPageId = "& Id)
  If Child.EOF Or Child.BOF then
      GetChilds = false
  Else
      While not Child.EOF
              Niveau = Child("Niveau")
            Select Case Niveau
                Case "2"
                    GetChilds = GetChilds & "<img src=ingen.gif border=1 align=left width=20 height=2>"
                    GetChilds = GetChilds & ""& Child("Title") &" <br>"
                Case "3"
                    GetChilds = GetChilds & "<img src=ingen.gif border=1 align=left width=50 height=2>"
                    GetChilds = GetChilds & ""& Child("Title") &" <br>"
            End Select
          If not GetChilds(Child("PageId")) = false Then
              GetChilds = GetChilds & GetChilds(Child("PageId")) & "<br>"
          End If
      Child.MoveNext
      wend
 
  End If
End Function


Det virker, men kan det laves smartere?
Avatar billede skg Nybegynder
22. december 2002 - 14:56 #12
JA... fjern Niveau feltet igen !

Du kan jo altid finde ud af hvor du er henne af, når du alligevel vil lave en masse opslag i din database.

Hvis det stod til mig at lave sådan en breadcrumb, ville det nok se nogenlunde sådan her ud:


Function WriteBreadCrumb( ByRef aPageId, ByRef aConn )

  Dim Rs, ParentID, Pages(), PageCount, I

  ' Opret forbindelsen hvis den er NULL
  If IsNull(aConn) Then
    Set aConn = Server.CreateObject("ADODB.Connection")
    Call aConn.Open("alle de der ting og sager man nu skal skrive")
  End If

  PageCount = CLng(0)
  Do While CLng(ParentID) <> CLng(0)
    ' Find siden ...
    Set Rs = aConn.Execute("Select * From [TABLE] Where PageID = " & aPageId)

    ' Check om den er fundet
    If Rs.Eof = False
      ' Gem info om siden
      Redim Preserve Pages(PageCount+1)
      Pages(PageCount) = Array(CStr(Rs("PageName")),Clng(Rs("PageID")))
      PageCount = CLng(PageCount+1)
    ' Ellers hop ud, der er noget galt ...
    Else
      Exit Do
    End If
    ' Smid Rs væk
    Set Rs = Nothing
  Loop

  For I = PageCount To 0
    ' Indsæt seperator eller ej ...
    If I > 0 Then Response.Write(" > ")
      Response.Write( "<a href=""link.fil?id=" & Pages(I)(1) & """>" & Pages(I)(0) & "</a>"

  Next

End Function

Call WriteBreadCrumb( 1234, Null )
Avatar billede weiland Nybegynder
22. december 2002 - 19:52 #13
skq >> Jeg forstår desværre ikke din løsning, og kan ikke få den til at virke, men den er sikkert OK med den rigtige tilretning.

Derimod har jeg anvendt cyberfessors løsningsmodel til at finde forældrene til en side. Koden er således:

Function GetParents(Id)
  SQL = "SELECT * FROM Pages WHERE (PageId = "& Id &")"
  Set Parent = MyConn.Execute(SQL)
      If Parent.EOF Or Parent.BOF OR (Id = 0) then
          GetParents = false
      Else
            While not Parent.EOF
                GetParents = GetParents & ""& Parent("Title") &" <br>"
              If not GetParents(Parent("ParentPageId")) = false Then
                  GetParents = GetParents & GetParents(Parent("ParentPageId")) & "<br>"
              End If
          Parent.MoveNext
          wend
     
      End If
 
  Parent.Close
  Set Parent = Nothing
End Function

PageID = "16"

Set RS = MyConn.Execute("SELECT * FROM Pages WHERE PageId = "& PageID &"")

    Response.Write "<b>"& RS("Title") &"</b><br>"
    Response.Write ""& GetParents(rs("ParentPageID"))

rs.Close
Set rs = Nothing

Problemet er nu, at siderne skrives omvendt, således at childs kommer først og parents til sidst.
Det skal vel løses med et array, men det kæmper jeg lidt med i øjeblikket....

Nogen forslag?
Avatar billede skg Nybegynder
23. december 2002 - 05:40 #14
jamen ... er det du prøver på ikke at lave breadcrumbs ?

så skal du jo netop bruge sådan en function som jeg lavede !

jeg har lige testet den, og rettet hvad jeg kunne finde:


Function WriteBreadCrumb( ByRef aPageId, ByRef aConn )

  Dim Rs, ParentID, Pages(100000), PageCount, I


  PageCount = CLng(0)
  ParentID  = aPageId

  Do While CLng(ParentID) <> CLng(0)
    ' Find siden ...
    Set Rs = aConn.Execute("Select * From tblPages Where id = " & ParentID)

    ' Check om den er fundet
    If Rs.Eof = False Then
      ' Gem info om siden
      ParentID = CLng(Rs("parent"))
      Pages(PageCount) = Array(CStr(Rs("name")),Clng(Rs("id")))
      PageCount = CLng(PageCount+1)

    ' Ellers hop ud, der er noget galt ...
    Else
      Exit Do
    End If
    ' Smid Rs væk
    Set Rs = Nothing
  Loop

  For I = PageCount-1 To 0 Step -1

    ' Indsæt seperator eller ej ...
    If I <> PageCount-1 Then Response.Write(" > ")
    Response.Write( "<a href=""link.fil?id=" & Pages(I)(1) & """>" & Pages(I)(0) & "</a>")

  Next

End Function

og tabellen ser sådan ud:

Id    Identifier (auto/long)
Parent Long
Name  String
Avatar billede weiland Nybegynder
23. december 2002 - 08:46 #15
Din løsning virker fint, og du har fortjent 100 points, men denne løsning virker også:

'OPSLAG

Function GetParents(Id)

Dim strTitle

  SQL = "SELECT * FROM Pages WHERE (PageId = "& Id &")"
  Set oRS = MyConn.Execute(SQL)
      If oRS.EOF Or oRS.BOF OR (Id = 0) then
          strTitle = ""
      Else
            While not oRS.EOF
                strTitle = strTitle & "<a href=default.asp?PageID="& oRS("PageID") &">"& oRS("Title") &"</a> > ;"
              If not GetParents(oRS("ParentPageId")) = "" Then
                  strTitle = strTitle & GetParents(oRS("ParentPageId")) & " "
              End If
          oRS.MoveNext
          wend
     
      End If
 
  oRS.Close
  Set oRS = Nothing
 
  GetParents = strTitle
End Function

PageID = "16"

Set rs = MyConn.Execute("SELECT * FROM Pages WHERE PageId = "& PageID &"")

    strTitle = ""& rs("Title") &"; "& GetParents(rs("ParentPageID")) &""

    x = Split(strTitle, ";")
   
    For t = UBound(x) To 0 Step -1
        Response.Write(x(t) & " ")
    Next


rs.Close
Set rs = Nothing
Avatar billede skg Nybegynder
23. december 2002 - 08:54 #16
du bestemmer jo selv hvad du vil bruge, men tænk nu lidt over at lave genbrugelig kode - altså ikke mente at du skal copy-paste det ind overalt
Avatar billede burningice Nybegynder
24. december 2002 - 11:47 #17
svar

Glædelig jul til jer alle :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester