Dette ligner ikke et anstændigt design for hierarkiske data. Overvej en anden tilgang, såsom adjacency list .
Løsning #1 - MySQL 8 JSON-understøttelse:
Med MySQL 8 kan du bruge JSON_ARRAYAGG()
og JSON_OBJECT()
for at få JSON-resultatet kun med SQL:
vælg json_object( 'name', l1.level_1_name, 'children', json_arrayagg(json_object('name', l2.level_2_name, 'children', l2.children))) som jsonfrom level_1 l1left join ( vælg l2.level_2_name , l2.level_1_fk , json_arrayagg(json_object('name', l3.level_3_name)) som børn fra level_2 l2 venstre slutter sig til level_3 l3 på l3.level_2_fk =l2.level_2_pk-gruppe på l2.level_level_k_1 på l2.level.k_1 l1.level_1_pkgroup efter level_1_pk
Resultatet er:
{"name":"Bob", "children":[{"name":"Ted", "children":[{"name":"Fred"}]}, {"name" :"Carol", "children":[{"name":"Harry"}]}, {"name":"Alice", "children":[{"name":"Mary"}]}]}
Formateret:
{ "name":"Bob", "children":[ { "name":"Ted", "children":[ { "name":"Fred" } ] }, { "name" :"Carol", "children":[ { "name":"Harry" } ] }, { "name":"Alice", "children":[ { "name":"Mary" } ] } ]}
Løsning #2 - Konstruktion af JSON med GROUP_CONCAT():
Hvis navnene ikke indeholder nogen citattegn, kan du manuelt konstruere JSON-strengen i ældre versioner ved hjælp af GROUP_CONCAT()
:
$query =<<
Resultatet ville være det samme (se demo )
Løsning #3 - Konstruktion af nestet-struktur med PHP-objekter:
Du kan også skrive en enklere SQL-forespørgsel og konstruere den indlejrede struktur i PHP:
$result =$connection->query(" vælg level_1_name som navn, null som overordnet fra level_1 union alle vælg l2.level_2_name som navn, l1.level_1_name som forælder fra level_2 l2 join level_1 l1 på l1.level_1_pk =l2.level_1_fk union alle vælg l3.level_3_name som navn, l2.level_2_name som forælder fra level_3 l3 join level_2 l2 på l2.level_2_pk =l3.level_2_fk");
Resultatet er
navn | forælder----------------Bob | nullTed | BobCarol | BobAlice | BobFred | TedHarry | CarolMary | Alice
Bemærk:Navnet skal være unikt langs alle tabeller. Men jeg ved ikke, hvilket resultat du ville forvente, hvis dubletter var mulige.
Gem nu rækkerne som objekter i en matrix indekseret med navnet:
$data =[]while ($row =$result->fetch_object()) { $data[$row->name] =$row;}
$data
vil nu indeholde
[ 'Bob' => (objekt)['name' => 'Bob', 'forælder' => NULL], 'Ted' => (objekt)['name' => 'Ted' , 'forælder' => 'Bob'], 'Carol' => (objekt)['name' => 'Carol', 'forælder' => 'Bob'], 'Alice' => (objekt)['navn ' => 'Alice', 'forælder' => 'Bob'], 'Fred' => (objekt)['name' => 'Fred', 'forælder' => 'Ted'], 'Harry' => (objekt)['name' => 'Harry', 'forælder' => 'Carol'], 'Mary' => (objekt)['name' => 'Mary', 'forælder' => 'Alice'] ,]
Vi kan nu forbinde noderne i en enkelt sløjfe:
$roots =[];foreach ($data som $row) { if ($row->parent ===null) { $roots[] =$row; } else { $data[$row->parent]->children[] =$row; } unset($row->forælder);}echo json_encode($roots[0], JSON_PRETTY_PRINT);
Resultatet:
{ "name":"Bob", "children":[ { "name":"Ted", "children":[ { "name":"Fred" } ] }, { "name" :"Carol", "children":[ { "name":"Harry" } ] }, { "name":"Alice", "children":[ { "name":"Mary" } ] } ]}
Hvis flere rodnoder er mulige (flere rækker i niveau_1_navn
), og brug derefter
json_encode($roots);