Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Membuat JSON hierarkis dari hasil MySQL dan PHP untuk pohon D3.js?

Ini tidak terlihat seperti desain yang layak untuk data hierarkis. Pertimbangkan pendekatan lain seperti daftar kedekatan .

Solusi #1 - Dukungan MySQL 8 JSON:

Dengan MySQL 8 Anda dapat menggunakan JSON_ARRAYAGG() dan JSON_OBJECT() untuk mendapatkan hasil JSON hanya dengan SQL:

select json_object(
  'name', l1.level_1_name,
  'children', json_arrayagg(json_object('name', l2.level_2_name, 'children', l2.children))
) as json
from level_1 l1
left join (
  select l2.level_2_name
       , l2.level_1_fk
       , json_arrayagg(json_object('name', l3.level_3_name)) as children
  from level_2 l2
  left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
  group by l2.level_2_pk
) l2 on l2.level_1_fk = l1.level_1_pk
group by level_1_pk

Hasilnya adalah:

{"name": "Bob", "children": [{"name": "Ted", "children": [{"name": "Fred"}]}, {"name": "Carol", "children": [{"name": "Harry"}]}, {"name": "Alice", "children": [{"name": "Mary"}]}]}

demo db-fiddle

Diformat:

{
    "name": "Bob",
    "children": [
        {
            "name": "Ted",
            "children": [
                {
                    "name": "Fred"
                }
            ]
        },
        {
            "name": "Carol",
            "children": [
                {
                    "name": "Harry"
                }
            ]
        },
        {
            "name": "Alice",
            "children": [
                {
                    "name": "Mary"
                }
            ]
        }
    ]
}

Solusi #2 - Membangun JSON dengan GROUP_CONCAT():

Jika nama tidak mengandung carachter kutipan, Anda dapat membuat string JSON secara manual di versi lama menggunakan GROUP_CONCAT() :

$query = <<<MySQL
    select concat('{',
      '"name": ', '"', l1.level_1_name, '", ',
      '"children": ', '[', group_concat(
        '{',
        '"name": ', '"', l2.level_2_name, '", ',
        '"children": ', '[', l2.children, ']',
        '}'
      separator ', '), ']'        
    '}') as json
    from level_1 l1
    left join (
      select l2.level_2_name
           , l2.level_1_fk
           , group_concat('{', '"name": ', '"',  l3.level_3_name, '"', '}') as children
      from level_2 l2
      left join level_3 l3 on l3.level_2_fk = l2.level_2_pk
      group by l2.level_2_pk
    ) l2 on l2.level_1_fk = l1.level_1_pk
    group by level_1_pk
MySQL;

Hasilnya akan sama (lihat demo )

Solusi #3 - Membangun struktur nestet dengan objek PHP:

Anda juga dapat menulis kueri SQL yang lebih sederhana dan membuat struktur bersarang di PHP:

$result = $connection->query("
    select level_1_name as name, null as parent
    from level_1
    union all
    select l2.level_2_name as name, l1.level_1_name as parent
    from level_2 l2
    join level_1 l1 on l1.level_1_pk = l2.level_1_fk
    union all
    select l3.level_3_name as name, l2.level_2_name as parent
    from level_3 l3
    join level_2 l2 on l2.level_2_pk = l3.level_2_fk
");

Hasilnya adalah

name    | parent
----------------
Bob     | null
Ted     | Bob
Carol   | Bob
Alice   | Bob
Fred    | Ted
Harry   | Carol
Mary    | Alice

demo

Catatan:Nama harus unik di sepanjang semua tabel. Tapi saya tidak tahu apa hasil yang Anda harapkan, jika duplikat mungkin terjadi.

Sekarang simpan baris sebagai objek dalam array yang diindeks dengan nama:

$data = []
while ($row = $result->fetch_object()) {
    $data[$row->name] = $row;
}

$data sekarang akan berisi

[
    'Bob'   => (object)['name' => 'Bob',   'parent' => NULL],
    'Ted'   => (object)['name' => 'Ted',   'parent' => 'Bob'],
    'Carol' => (object)['name' => 'Carol', 'parent' => 'Bob'],
    'Alice' => (object)['name' => 'Alice', 'parent' => 'Bob'],
    'Fred'  => (object)['name' => 'Fred',  'parent' => 'Ted'],
    'Harry' => (object)['name' => 'Harry', 'parent' => 'Carol'],
    'Mary'  => (object)['name' => 'Mary',  'parent' => 'Alice'],
]

Sekarang kita dapat menautkan node dalam satu loop:

$roots = [];
foreach ($data as $row) {
    if ($row->parent === null) {
        $roots[] = $row;
    } else {
        $data[$row->parent]->children[] = $row;
    }
    unset($row->parent);
}

echo json_encode($roots[0], JSON_PRETTY_PRINT);

Hasilnya:

{
    "name": "Bob",
    "children": [
        {
            "name": "Ted",
            "children": [
                {
                    "name": "Fred"
                }
            ]
        },
        {
            "name": "Carol",
            "children": [
                {
                    "name": "Harry"
                }
            ]
        },
        {
            "name": "Alice",
            "children": [
                {
                    "name": "Mary"
                }
            ]
        }
    ]
}

demo

Jika beberapa simpul akar dimungkinkan (beberapa baris di level_1_name ), lalu gunakan

json_encode($roots);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. MySqli:apakah mungkin membuat database?

  2. Salin/duplikat baris SQL dengan gumpalan/teks, Bagaimana caranya?

  3. Tidak dapat mengambil id baris menggunakan pdo

  4. Bisakah saya menggunakan pt-online-schema-change untuk mengubah kunci utama?

  5. Cara mengelompokkan berdasarkan pesanan DESC