当没有预定义父 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;
}
我正在使用 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;
}