Avatar billede kongknabe Nybegynder
28. juni 2012 - 16:20 Der er 5 kommentarer

Hjælp til query af nested data.

Jeg har en database struktur der ser nogenlunde sådan her ud:

------------------------------------
| ID          | Parent ID          | type              |
------------------------------------
| 1            | null                  | Folder          |
| 2            | 1                      | Folder          |
| 3            | 2                      | Folder          |
| 4            | 3                      | Folder          |
| 5            | 3                      | Content      |
| 6            | 3                      | Folder          |
| 7            | 6                      | Content      |
| 8            | 6                      | Content      |
------------------------------------


Det jeg ønsker er at trække ID'er på alt "content" der enten er relateret til folderen med ID 3 content i alle de foldere der er relateret til folder med ID 3, og så fremdeles.. Altså ønsker jeg at kunne hoppe ind et bestemt sted i dette hierarkiet og få alt content der ligger under..

Kan dog ikke lige overskue hvordan jeg skriver en sådan query, og om det i det hele taget er muligt med den database struktur?
Avatar billede arne_v Ekspert
29. juni 2012 - 00:51 #1
MySQL har ingen features som goer dette nemt.

Hvis du kan have alle data i memory, saa laes dem op i memory.
Avatar billede kongknabe Nybegynder
29. juni 2012 - 09:20 #2
Takker for dit svar, men er ikke sikker på hvad du mener, og kan ikke finde ud af at skrive en query der trækkker den ønskede data ud.
Avatar billede kongknabe Nybegynder
29. juni 2012 - 10:01 #3
Men efter at have ledt lidt rundt på google begynder jeg at tænke at databasen nok skal struktureres anderledes...
Avatar billede majbom Novice
29. juni 2012 - 15:32 #4
hvad bruger du sammen med mysql? php?

så kunne du jo lave en rekursiv funktion, der kan hvad du ønsker
Avatar billede arne_v Ekspert
30. juni 2012 - 23:59 #5
Kode snippets:


CREATE TABLE treedemo (
    id INTEGER NOT NULL,
    parentid INTEGER,
    typ VARCHAR(20),
    PRIMARY KEY(id)
);

INSERT INTO treedemo VALUES(1,null,'Folder');
INSERT INTO treedemo VALUES(2,1,'Folder');
INSERT INTO treedemo VALUES(3,2,'Folder');
INSERT INTO treedemo VALUES(4,3,'Folder');
INSERT INTO treedemo VALUES(5,3,'Content');
INSERT INTO treedemo VALUES(6,3,'Folder');
INSERT INTO treedemo VALUES(7,6,'Content');
INSERT INTO treedemo VALUES(8,6,'Content');



<?php
class Record {
    public $id;
    public $parentid;
    public $typ;
    public function __construct($id, $parentid, $typ) {
        $this->id = $id;
        $this->parentid = $parentid;
        $this->typ = $typ;
    }
};

function load_children($currentid, $con, &$list) {
    $stmt = $con->prepare('SELECT id,parentid,typ FROM treedemo WHERE parentid=?');
    $stmt->bind_param('i', $currentid);
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($id, $parentid, $typ);
    $folders = array();
    while($stmt->fetch()) {
        if($typ == 'Content') {
            $list[] = new Record($id, $parentid, $typ);
        } else if($typ == 'Folder') {
            $folders[] = $id;
        }
    }
    $stmt->close();
    foreach($folders as $folderid) {
        load_children($folderid, $con, $list);
    }
}

function load($startid) {
    $list = array();
    $con = new mysqli('localhost', 'root', '', 'Test');
    $stmt = $con->prepare('SELECT id,parentid,typ FROM treedemo WHERE id=?');
    $stmt->bind_param('i', $startid);
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($id, $parentid, $typ);
    $children = false;
    if($stmt->fetch()) {
        if($typ == 'Content') {
            $list[] = new Record($id, $parentid, $typ);
        } else if($typ == 'Folder') {
            $children = true;
        }
    }
    $stmt->close();
    if($children) {
        load_children($startid, $con, $list);
    }
    $con->close();
    return $list;
}

$all3 = load(3);
foreach($all3 as $one3) {
    echo $one3->id . ' ' . $one3->typ . "<br>\r\n";
}
$all8 = load(8);
foreach($all8 as $one8) {
    echo $one8->id . ' ' . $one8->typ . "<br>\r\n";
}
$all9 = load(9);
foreach($all9 as $one9) {
    echo $one9->id . ' ' . $one9->typ . "<br>\r\n";
}
$t1 = microtime(true);
for($i = 0; $i < 1000; $i++) {
    load(3);
}
$t2 = microtime(true);
echo ($t2 - $t1) . "<br>\r\n";
?>



<?php
class Record {
    public $id;
    public $parentid;
    public $typ;
    public $children;
    public function __construct($id, $parentid, $typ) {
        $this->id = $id;
        $this->parentid = $parentid;
        $this->typ = $typ;
        $this->children = array();
    }
};

function loadall() {
    $list = array();
    $con = new mysqli('localhost', 'root', '', 'Test');
    $stmt = $con->prepare('SELECT id,parentid,typ FROM treedemo');
    $stmt->execute();
    $stmt->store_result();
    $stmt->bind_result($id, $parentid, $typ);
    while($stmt->fetch()) {
        $list[$id] = new Record($id, $parentid, $typ);
        if($parentid != null) $list[$parentid]->children[] = $id;
    }
    $stmt->close();
    $con->close();
    return $list;
}

function load_children($currentid, $all, &$list) {
    $folders = array();
    foreach($all[$currentid]->children as $childid) {
        $child = $all[$childid];
        if($child->typ == 'Content') {
            $list[] = $child;
        } else if($child->typ == 'Folder') {
            $folders[] = $child->id;
        }
    }
    foreach($folders as $folderid) {
        load_children($folderid, $all, $list);
    }
}

function load($startid, $all) {
    $list = array();
    $children = false;
    if(array_key_exists($startid, $all)) {
        $startrec = $all[$startid];
        if($startrec->typ == 'Content') {
            $list[] = $startrec;
        } else if($startrec->typ == 'Folder') {
            $children = true;
        }
    }
    if($children) {
        load_children($startid, $all, $list);
    }
    return $list;
}

$all = loadall();
$all3 = load(3, $all);
foreach($all3 as $one3) {
    echo $one3->id . ' ' . $one3->typ . "<br>\r\n";
}
$all8 = load(8, $all);
foreach($all8 as $one8) {
    echo $one8->id . ' ' . $one8->typ . "<br>\r\n";
}
$all9 = load(9, $all);
foreach($all9 as $one9) {
    echo $one9->id . ' ' . $one9->typ . "<br>\r\n";
}
$t1 = microtime(true);
for($i = 0; $i < 1000; $i++) {
    load(3, $all);
}
$t2 = microtime(true);
echo ($t2 - $t1) . "<br>\r\n";
?>
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