Avatar billede codebase Praktikant
03. oktober 2001 - 18:16 Der er 25 kommentarer og
1 løsning

Sql order by ? JOIN ??

Jeg har en menu tabel, med kollonerne:
id name parent_id placement


indholdet kunne være:
id name        parent_id  placement
1  codebase1      0          1
2  codebase2      0          2
3  codebase1.1    1          1
4  codebase1.2    1          2
5  codebase2.1    2          1
6  codebase1.2.1  4          2
7  codebase2.1.1  5          1
8  codebase3      0          3
...
..
27 hest          3          1



Nu ville jeg gerne i EN sql sætning, liste menu punkterne i den rigtige rækkefølge:

dvs. noget med en ORDER BY parent_id.
Men for for hver parent_id , skal de menupunkter der er tilknyttet via parent_id = id nummeret, listes efterfølgende..


1  codebase1      0          1
3  codebase1.1    1          1
27 hest          3          1
4  codebase1.2    1          2
6  codebase1.2.1  4          2
2  codebase2      0          2
5  codebase2.1    2          1
7  codebase2.1.1  5          1
8  codebase3      0          3

_codeb@se.


Avatar billede mukke Nybegynder
03. oktober 2001 - 18:25 #1
Jeg er ikek helt sikker, men kan du ikke bare bruge:

SELECT *
FROM menu_tabel
ORDER BY parent_id, placement;
Avatar billede mukke Nybegynder
03. oktober 2001 - 18:25 #2
nej undskyld det er helt hen i vejret....
Avatar billede mortenfn Nybegynder
03. oktober 2001 - 19:55 #3
kan du ikke bare

select * fron tabel order by placement,name,parent_id 

hov du - dir output er da ikke sorteret
Avatar billede codebase Praktikant
03. oktober 2001 - 20:04 #4
->mukke :-)
->mortenfn nej, det vil ikke virke..

måske er det ikke muligt, det jeg ønsker.
Alternativet, ville være to sql-sætninger.

Den første der henter DISTINCT parent_id, med ORDER BY parent_id

derefter en der henter alle \'sub\' parent_id ORDER BY placement


...

_codeb@se.
Avatar billede mukke Nybegynder
03. oktober 2001 - 20:09 #5
Er bange for du nok bliver nødt til at lave det på den alternative måde... i en eller anden form for rekursiv konstruktion:

function hent_linier(id)
{
  sql_select alle linier med parent_id = id
  for hver linie
  {
    returner linie
    hent_linier(linie.id)
  }
}

funktion hent_alt
{
  returner hent_linier(0)
}


Lidt pseudo-kode - håber det kan bruges.
Avatar billede codebase Praktikant
04. oktober 2001 - 15:54 #6
oki, kukke

jeg tror på at det skal gøres via et par funktioner..

Men syntes ikke lige jeg kan se hvad du mener..

Måske kunne du lave et eks. med de paremeter jeg har valgt (parent_id, placement...)

_codebase.
Avatar billede codebase Praktikant
04. oktober 2001 - 16:20 #7
det virker , men jeg har ikke fundet den rigtige metode endnu, tror jeg....

http://www.codebase.dk/test/menu.php

Avatar billede mukke Nybegynder
04. oktober 2001 - 16:35 #8
Jeg skrev det som jeg gjorde fordi jeg ikke vidste hvilket sprog du programmerer i. ;-)

Og jeg har ikke selv erfaring med PHP.

ideen er at du har en metode der udskriver alle linier med det id den bliver kaldt.
Samtidig vil den for hver udskrevet linie kalde sig selv med den udskrevne linies ID.

Ved at kalde denne metode først med id = 0, vil du opnå en rekursiv effekt hvor alt udskrives:

fra ovenstående eksempel:

1) udskriv resultet af hent_linier(0)

i hent linier vil vi nu få følgende recordset:
id name        parent_id  placement
1  codebase1      0          1
2  codebase2      0          2
8  codebase3      0          3

og metoden vil arbejde sig igennem ved først at returnere
1  codebase1      0          1
og herefter udskrive hent_linier(1)

altså er vi nu igen i toppen af en ny instans af hent linier, og vi vil få fat i følgende recordset:

id name        parent_id  placement
3  codebase1.1    1          1
4  codebase1.2    1          2

altså vil vi returnere
3  codebase1.1    1          1
samt returnere resultatet af hent_linier(3)

Den nye udgave af hent_linler vil få et tomt recordset (ingen poster har parent_id=3) og vil altså ikke returnere noget.

så er vi tilbage i hent_linier fra før og returnerer nu den næste post
4  codebase1.2    1          2
og hent_lininer(4) kaldes
...

Er du med? ellers kan jeg næsten ikke forklare det nærmere....
Avatar billede codebase Praktikant
04. oktober 2001 - 16:42 #9
jeg forstår det, og det virker..
Men jeg er ikke med på hvordan, jeg får resultatet ud af mit \'multi\' array...

http://www.codebase.dk/test/menu.php

min funktion:
function hent_linier($id) {
  $sql=\"SELECT DISTINCT menu.id, menu.name , menu.parent_id, menu.placement FROM menu WHERE parent_id = \'$id\' ORDER BY parent_id ASC , placement ASC\";
    $result  =  mysql_query(\"$sql\");
    $k=0;
    for($j = $k; $row  =  mysql_fetch_object($result);$j++) {
        $array[$j][0]=$row->id;
        $array[$j][1]=$row->name;
      $subarray = hent_linier($row->id);
     
      $array[$j][2]= hent_linier($row->id);
    }
    return $array;
}

function hent_alt() {
  return hent_linier(0);
}


Er det forkert at bruge array... !!??
Avatar billede codebase Praktikant
04. oktober 2001 - 16:43 #10
linen $subarray = hent_linier($row->id); er en gammel line, og skal ikke bruges...
Avatar billede mukke Nybegynder
04. oktober 2001 - 16:52 #11
Jeg er ikke 100% sikker på hvordan det du har lavet fungerer, men umiddelbartvil jeg synes dette ville være nemmere:

$index = 0; // Bemærk denne skulle gerne være \"global\".

function hent_linier($id) {
  $sql=\"SELECT DISTINCT menu.id, menu.name , menu.parent_id, menu.placement FROM menu WHERE parent_id = \'$id\' ORDER BY parent_id ASC , placement ASC\";
    $result  =  mysql_query(\"$sql\");
    for( ; $row  =  mysql_fetch_object($result);$index++) {
        $array[$index][0]=$row->id;
        $array[$j][1]=$row->name;
        hent_linier($row->id);
    }
}

function hent_alt() {
  hent_linier(0);
}

//

Frem for at returnerere delresultaterne har jeg nu lavet så det gemmes i et globalt array (Dette skal nok erklæres - er ikke helt sikker på hvordan det skal gøres i PHP :)

Det ville naturligvis være mere elegant at bruge \"return\" metoden, men jeg ved ikke lige hvordan vi let kan kopiere indholdet af et array over i et andet, men hvis det er muligt så kan en lille ændring til det du har være at udskifte følgende:

      $subarray = hent_linier($row->id);
     
      $array[$j][2]= hent_linier($row->id);

med


      $subarray = hent_linier($row->id);
     
      for hvert element i $subarray, kopier det til $array.

Som det er lige nu lægger du tilsyneladende X-elementer (et array) ind på et enkelt elements plads.
Avatar billede codebase Praktikant
04. oktober 2001 - 17:32 #12
jeg valgte den \'rigtige\' løsning, og bruger return i mine funktion..

function hent_linier($id) {
  $sql=\"SELECT DISTINCT menu.id, menu.name , menu.parent_id, menu.placement FROM menu WHERE parent_id = \'$id\' ORDER BY parent_id ASC , placement ASC\";
    $result  =  mysql_query(\"$sql\");
    for($j = 1; $row  =  mysql_fetch_object($result);$j++) {
        if (!$k) $k = $j;
        $array[$k][0]=$row->id;
        $array[$k][1]=$row->name;
        $array[$k][2]=$row->parent_id;
        $array[$k][3]=$row->placement;
      $subarray = hent_linier($row->id);
        if (count($subarray) > 0) {     
          foreach($subarray AS $key => $value) {
              $k++;
                $array[$k][0]=$value[0];
                $array[$k][1]=$value[1];
                $array[$k][2]=$value[2];
                $array[$k][3]=$value[3];
          }
      }
        $k++;
    }
    return $array;
}

function hent_alt() {
  return hent_linier(0);
}


Takker for hjælpen, og regner bestemt med at kunne bruge denne funktion i fremtiden.. :-)

Men, jeg ville gerne se den løsning hvor dette blev gjort i en Sql-sætning... Det må da være muligt...

_codeb@se.
Avatar billede codebase Praktikant
04. oktober 2001 - 17:36 #13
det er meget sjovt at læse dette spg. igennem, mukke\'s første par svar...*gg*

...og så løber han med de 30 points.. *S*


.. codebase ..
Avatar billede mukke Nybegynder
04. oktober 2001 - 17:44 #14
Tak for pointsene, jeg håber da bestemt at du kan bruge om ikke metoden så ideen i fremtiden!

Jeg tror ikke det er muligt at løse dette med almindelige SQL-komandoer pga. det rekursive element, men det er da meget tænkeligt at man kunne lave noget smart med \"stored procedures\" som jeg dog overhovedet ikke selv har arbejdet med.
Avatar billede codebase Praktikant
04. oktober 2001 - 18:55 #15
.. hvordan skal/kan jeg lave et tree ??

Sådan så man kan se hvilke menupunkter der ligger under, et menupunkt ??

se evt.  http://www.codebase.dk/test/menu.php
Avatar billede codebase Praktikant
04. oktober 2001 - 18:57 #16
$menu = hent_alt();

foreach ($menu AS $key => $subarray) {
        if ($subarray[2] == 0) unset($index);
    if ($subarray[3] == 1  && $subarray[2] != 0){
            $index.=\" \";
    }       
    echo $index.$subarray[1].\"<br>\";
    $array[$key][0]=$subarray[0];
    $array[$key][1]=$index.$subarray[1];
}

herefter er det $array, der udskrives i den dropdown boks..
Avatar billede mukke Nybegynder
04. oktober 2001 - 19:03 #17
Umiddelelbart ser det da ud til det virker nu.. eller overser jeg noget?
Avatar billede codebase Praktikant
04. oktober 2001 - 19:04 #18
menupunkt jha1.2 skulle et \'hak\' tilbage... da det ligger på samme nevau som jha1.1 !

Avatar billede mukke Nybegynder
04. oktober 2001 - 19:13 #19
ah ok... man kunne evt. modificere hent_linier en smule:

function hent_linier($id, $niveau) {
...
for ($n = 0; $n < $niveu; $n++)
{
  $array[$k][4] .= \'&nbsp;\";
}
...
$subarray = hent_linier($row->id, $niveau+1);
...
function hent_alt() {
  return hent_linier(0,1);
}


når det så skal indrykke kan du bare udskrive det 5. element i arrayet.
Avatar billede codebase Praktikant
04. oktober 2001 - 22:56 #20
..det virker ikke ..
Avatar billede codebase Praktikant
05. oktober 2001 - 14:17 #21
nummer 1.3.1 og 1.3.2, rykker ikke ind, som de bør.

Dvs. det virker kun i niveau 1....

-codeb@se.
Avatar billede codebase Praktikant
05. oktober 2001 - 14:18 #22
function Get_Category_Id($id,$niveau) {
  $sql=\"SELECT DISTINCT menu.id, menu.name , menu.parent_id, menu.placement FROM menu WHERE parent_id = \'$id\' ORDER BY parent_id ASC , placement ASC\";
    $result  =  mysql_query(\"$sql\");
    for($j = 1; $row  =  mysql_fetch_object($result);$j++) {
        if (!$k) $k = $j;
        $array[$k][0]=$row->id;
        $array[$k][1]=$row->name;
        $array[$k][2]=$row->parent_id;
        $array[$k][3]=$row->placement;
      $subarray = Get_Category_Id($row->id, $niveau);
        if (count($subarray) > 0) {     
          foreach($subarray AS $key => $value) {
              $k++;
                $array[$k][0]=$value[0];
                $array[$k][1]=$value[1];
                $array[$k][2]=$value[2];
                $array[$k][3]=$value[3];
                for ($n = 0; $n < $niveau; $n++){
                  $array[$k][4] .= \"&nbsp;\";
                }
          }
      }
        $k++;
    }
    return $array;
}

function Get_All_Category_Id() {
  return Get_Category_Id(0,1);
}
Avatar billede mukke Nybegynder
05. oktober 2001 - 16:00 #23
Du har lagt min for-lykke det forkerte sted som jeg umiddelbart kan se det.. flyt den ud til at stå lige efter linien

$array[$k][3]=$row->placement;

og i udvid foreach-lykken med en ekstra linie:
$array[$k][4]=$value[4];
Avatar billede codebase Praktikant
05. oktober 2001 - 16:06 #24
Sådan ?? (det blev det ikke bedre af...!)

function Get_Category_Id($id,$niveau) {
  $sql=\"SELECT DISTINCT menu.id, menu.name , menu.parent_id, menu.placement FROM menu WHERE parent_id = \'$id\' ORDER BY parent_id ASC , placement ASC\";
    $result  =  mysql_query(\"$sql\");
    for($j = 1; $row  =  mysql_fetch_object($result);$j++) {
        if (!$k) $k = $j;
        $array[$k][0]=$row->id;
        $array[$k][1]=$row->name;
        $array[$k][2]=$row->parent_id;
        $array[$k][3]=$row->placement;
        for ($n = 0; $n < $niveau; $n++){
            $array[$k][4] .= \"&nbsp;\";
        }
      $subarray = Get_Category_Id($row->id, $niveau);
        if (count($subarray) > 0) {     
          foreach($subarray AS $key => $value) {
              $k++;
                $array[$k][0]=$value[0];
                $array[$k][1]=$value[1];
                $array[$k][2]=$value[2];
                $array[$k][3]=$value[3];
                $array[$k][4]=$value[4];
          }
      }
        $k++;
    }
    return $array;
}
Avatar billede mukke Nybegynder
05. oktober 2001 - 16:19 #25
Ahhh..


din linie
$subarray = Get_Category_Id($row->id, $niveau);
skal naturligvis være
$subarray = Get_Category_Id($row->id, $niveau+1);


(som jeg altså også havde skrevet i starten ;-)
Avatar billede codebase Praktikant
05. oktober 2001 - 16:23 #26
jeg opretter lige et spg. så du kan få 30 points, for dit svar..

Jeg syntes, det er lidt \'kuku\', den måde funktionen virker på, og har svært ved at forstå det... :-)
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
Computerworld tilbyder specialiserede kurser i database-management

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