当没有预定义父 ID 或子 ID 时,从 MySQL PHP 构建层次结构

Building hierarchies from MySQL PHP when no Parent or Child IDs are pre-defined

我正在使用 MySQL 5.7,所以理解 Common Table 表达式不可用,但我正在尝试找到一种方法来基于基于列的输入构建层次结构。

例如,我的 table 包含以下...

Region Office Person
Region 1 Office 1 Employee 1
Region 1 Office 1 Employee 2
Region 1 Office 2 Employee 1
Region 2 Office 1 Employee 1
Region 2 Office 2 Employee 1
Region 2 Office 2 Employee 2

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=049349ecdbf3369026e009dcb08b3c14

最初我曾问过(在另一个已关闭的问题中)有关如何使用动态生成的 ID 和 ParentID 实现这一点的方向,但如果没有大量的子查询,这似乎是不可能的。以不同的方式思考这个问题,这是否可以在 PHP 中实现,而不是构建一个数组?

假设数据库的结果符合 table...

<?php

$dbResponse = array(
  array(
    "Region" => "Region 1",
    "Office" => "Office 1",
    "Employee" => "Employee 1"
  ),
  array(
    "Region" => "Region 1",
    "Office" => "Office 1",
    "Employee" => "Employee 2"
  ),
  array(
    "Region" => "Region 1",
    "Office" => "Office 2",
    "Employee" => "Employee 1"
  ),
  array(
    "Region" => "Region 2",
    "Office" => "Office 1",
    "Employee" => "Employee 1"
  ) 
); // etc. etc. ...........


// Transformation here

如何对其进行转换才能产生所需的输出?

$newOutput = array(
  array(
    "Item" => "Region 1",
    "Children" => array(
                    "Item" => "Office 1",
                    "Children" => array(
                                    "Item" => array("Employee 1", "Employee 2")
                                    )
                    ),
                    array(
                    "Item" => "Office 2",
                    "Children" => array(
                                    "Item" => array("Employee 1")
                                    )
                    ),
  ), 
  array(
    "Item" => "Region 2",
    "Children" => array(
                    "Item" => "Office 1",
                    "Children" => array(
                                    "Item" => array("Employee 1")
                                    )
                    )
  )  
);

将嵌套转换为数组的最简单方法是 -

$newOutput = [];

foreach ($dbResponse as $row) {
    $newOutput[$row['Region']][$row['Office']][] = $row['Employee'];
}

这看起来像 -

Array
(
    [Region 1] => Array
        (
            [Office 1] => Array
                (
                    [0] => Employee 1
                    [1] => Employee 2
                )

            [Office 2] => Array
                (
                    [0] => Employee 1
                )

        )

    [Region 2] => Array
        (
            [Office 1] => Array
                (
                    [0] => Employee 1
                )

            [Office 2] => Array
                (
                    [0] => Employee 1
                    [1] => Employee 2
                )

        )

)

但是如果你真的需要实现你问题中建议的结构,那么你可以做类似 -

$newOutput2 = [];

// initialise 2 counters
$r = $o = 0;

$previousRow = null;

foreach($dbResponse as $row) {
    if (is_null($previousRow)) {
        // no counter manipulation required
    } elseif ($previousRow['Region'] == $row['Region'] && $previousRow['Office'] != $row['Office']) {
        $o++;
    } elseif ($previousRow['Region'] != $row['Region']) {
        $r++;
        $o = 0;
    }

    $newOutput2[$r]['Item'] = $row['Region'];
    $newOutput2[$r]['Children'][$o]['Item'] = $row['Office'];
    $newOutput2[$r]['Children'][$o]['Children']['Item'][] = $row['Employee'];

    $previousRow = $row;
}

这看起来像 -

Array
(
    [0] => Array
        (
            [Item] => Region 1
            [Children] => Array
                (
                    [0] => Array
                        (
                            [Item] => Office 1
                            [Children] => Array
                                (
                                    [Item] => Array
                                        (
                                            [0] => Employee 1
                                            [1] => Employee 2
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [Item] => Office 2
                            [Children] => Array
                                (
                                    [Item] => Array
                                        (
                                            [0] => Employee 1
                                        )

                                )

                        )

                )

        )

    [1] => Array
        (
            [Item] => Region 2
            [Children] => Array
                (
                    [0] => Array
                        (
                            [Item] => Office 1
                            [Children] => Array
                                (
                                    [Item] => Array
                                        (
                                            [0] => Employee 1
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [Item] => Office 2
                            [Children] => Array
                                (
                                    [Item] => Array
                                        (
                                            [0] => Employee 1
                                            [1] => Employee 2
                                        )

                                )

                        )

                )

        )

)

更新 对于将 Teams 添加到层次结构的示例,您可以向循环添加另一个深度级别 -

$newOutput3 = [];

// initialise 3 counters
$r = $o = $t = 0;

$previousRow = null;

foreach($dbResponse as $row) {
    if (is_null($previousRow)) {
        // no counter manipulation required
    } elseif ($previousRow['Region'] == $row['Region'] && $previousRow['Office'] == $row['Office'] && $previousRow['Team'] != $row['Team']) {
        $t++;
    } elseif ($previousRow['Region'] == $row['Region'] && $previousRow['Office'] != $row['Office']) {
        $o++;
        $t = 0;
    } elseif ($previousRow['Region'] != $row['Region']) {
        $r++;
        $o = $t = 0;
    }

    $newOutput3[$r]['Item'] = $row['Region'];
    $newOutput3[$r]['Children'][$o]['Item'] = $row['Office'];
    $newOutput3[$r]['Children'][$o]['Children'][$t]['Item'] = $row['Team'];
    $newOutput3[$r]['Children'][$o]['Children'][$t]['Children']['Item'][] = $row['Employee'];

    $previousRow = $row;
}