[MySQL]Retrieving single path
Ik heb een tabel met forums. Deze forums kunnen child van elkaar zijn.
Stel ik heb dit:
Ik ben in forum 5 en ik wil een lijst van de parents:
Dit dus. Gewoon dat een forum helemaal wordt terug geleid naar een forum van het hoogste nivo (parent = 0). Ik ben dus op zoek hoe ik dit het beste kan doen.
Ik had dit al gevonden (van MySQL docs):
Maar dat is niet wat ik zoek omdat ik gewoon een nieuwe result set wil hebben voor iedere parent en ik wil dat het dynamisch is, dus niet met lev1, 2, 3, 4, etc..
Dat is dus zeg maar wat ik zoek, maar ik wil niet met lft en rgt gaan werken. Eigenlijk is die mogenlijkheid er op dit moment helemaal niet van toepassing.
Dus iemand die mij kan helpen is altijd welkom!`
Stel ik heb dit:
Ik ben in forum 5 en ik wil een lijst van de parents:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
+-----+-----------------+
|Id |Forum |
+-----+-----------------+
|1 |Forum 1 |
|2 |Forum 2 |
|4 |Forum 4 |
|5 |Forum 5 |
+-----+-----------------+
|Id |Forum |
+-----+-----------------+
|1 |Forum 1 |
|2 |Forum 2 |
|4 |Forum 4 |
|5 |Forum 5 |
+-----+-----------------+
Dit dus. Gewoon dat een forum helemaal wordt terug geleid naar een forum van het hoogste nivo (parent = 0). Ik ben dus op zoek hoe ik dit het beste kan doen.
Ik had dit al gevonden (van MySQL docs):
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS' AND t4.name = 'FLASH';
+-------------+----------------------+-------------+-------+
| lev1 | lev2 | lev3 | lev4 |
+-------------+----------------------+-------------+-------+
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
+-------------+----------------------+-------------+-------+
1 row in set (0.01 sec)
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name = 'ELECTRONICS' AND t4.name = 'FLASH';
+-------------+----------------------+-------------+-------+
| lev1 | lev2 | lev3 | lev4 |
+-------------+----------------------+-------------+-------+
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
+-------------+----------------------+-------------+-------+
1 row in set (0.01 sec)
Maar dat is niet wat ik zoek omdat ik gewoon een nieuwe result set wil hebben voor iedere parent en ik wil dat het dynamisch is, dus niet met lev1, 2, 3, 4, etc..
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT parent.name
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.name = 'FLASH'
ORDER BY parent.lft;
+----------------------+
| name |
+----------------------+
| ELECTRONICS |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS |
| FLASH |
+----------------------+
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.name = 'FLASH'
ORDER BY parent.lft;
+----------------------+
| name |
+----------------------+
| ELECTRONICS |
| PORTABLE ELECTRONICS |
| MP3 PLAYERS |
| FLASH |
+----------------------+
Dat is dus zeg maar wat ik zoek, maar ik wil niet met lft en rgt gaan werken. Eigenlijk is die mogenlijkheid er op dit moment helemaal niet van toepassing.
Dus iemand die mij kan helpen is altijd welkom!`
Gesponsorde koppelingen:
Bump (half uurtje te vroeg :P)
wss... een vergelijking, met <> ? al draai je dan wel een grotere query, ik denk wel dat lefty en righty nodig zijn hiervoor... Mja, wss zit ik ernaast.
Eigenlijk heb je hier een WHILE lusje voor nodig, maar volgens mij mag je die alleen gebruiken binnen een FUNCTION of een PROCEDURE in MySQL. Op zich niet zo'n probleem, ware het niet dat MySQL volgens mij geen TABLE als return-type kent. M.a.w. je kan niet meerdere rijen teruggeven vanuit een functie.
Ik denk dat je er sneller uit komt door "gewoon" een PHP while-lusje en een prepared statement telkens opnieuw uit te voeren. Omdat je waarschijnlijk niet zo heel veel niveaus diep zal gaan, lijkt mij dit niet veel langzamer.
Ik denk dat je er sneller uit komt door "gewoon" een PHP while-lusje en een prepared statement telkens opnieuw uit te voeren. Omdat je waarschijnlijk niet zo heel veel niveaus diep zal gaan, lijkt mij dit niet veel langzamer.
Het liefst zou ik het met één query doen, zoals bij dat voorbeeld dat ik gaf, maar dan zonder left en right. Ik zat ook te denken aan een FUNCTION.
Dus het beste is gewoon alle items te selecteren en dan een lijst op te bouwen? Met PHP dus? En eventueel ook serverside caching dan..
Dit laat lokaal Apache crashen :S
Dus het beste is gewoon alle items te selecteren en dan een lijst op te bouwen? Met PHP dus? En eventueel ook serverside caching dan..
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
public function retrievePath($forum) {
$forumsModel = new forumsModel();
$forumsDump = $forumsModel->allForums();
foreach ($forumsDump as $forumData) $forumsData[$forumData['id']] = $forum;
return array_reverse(ForumsController::getParent($forum, $forumsData, array(array('id' => $forum, 'title' => $forumsData[$forum]['title']))));
}
public function getParent($forum, $forumsData, $currentTree) {
$currentTree[] = array('id' => $forumsData[$forum]['parent'], 'title' => $forumsData[$forumsData[$forum]['parent']]['title']);
if ($forumsData[$forum]['parent'] != 0) {
return ForumsController::getParent($forumsData[$forum]['parent'], $forumsData, $currentTree);
} else {
return $currentTree;
}
}
?>
public function retrievePath($forum) {
$forumsModel = new forumsModel();
$forumsDump = $forumsModel->allForums();
foreach ($forumsDump as $forumData) $forumsData[$forumData['id']] = $forum;
return array_reverse(ForumsController::getParent($forum, $forumsData, array(array('id' => $forum, 'title' => $forumsData[$forum]['title']))));
}
public function getParent($forum, $forumsData, $currentTree) {
$currentTree[] = array('id' => $forumsData[$forum]['parent'], 'title' => $forumsData[$forumsData[$forum]['parent']]['title']);
if ($forumsData[$forum]['parent'] != 0) {
return ForumsController::getParent($forumsData[$forum]['parent'], $forumsData, $currentTree);
} else {
return $currentTree;
}
}
?>
Dit laat lokaal Apache crashen :S
Gewijzigd op 01/01/1970 01:00:00 door Luuk Schakenraad
Ik neem aan dat zo'n pad niet dieper gaat dan bijvoorbeeld 3 of 4 niveaus. Is het dan niet handiger om "gewoon" 4 queries uit te voeren die ieder 1 resultaat opleveren, dan 1 query die een stuk of 30 resultaten oplevert? (ervan uitgaande dat je een redelijk uitgebreid forum gepland hebt, aangezien je al subcategorieën wilt introduceren :) )
De code is in ieder geval lekker simpel :)
De code is in ieder geval lekker simpel :)
Code (php)
Gewijzigd op 01/01/1970 01:00:00 door Jelmer rrrr



