我有一些分层数据,因此创建了它:
CREATE TABLE `departments`
(`deperatment_id` INTEGER NOT NULL,
`department_name` varchar(32) NOT NULL);
INSERT INTO `departments`(`deperatment_id`, `department_name`)
VALUES (1, "HR"), (2, "Software"), (3, "Accounts");
CREATE TABLE `jobs` (`deperatment_id` INTEGER NOT NULL,
`job_id` INTEGER NOT NULL,
`job_name` varchar(32) NOT NULL);
INSERT INTO `jobs` (`deperatment_id`, `job_id`, `job_name`)
VALUES (1, 1, "Idiot"),
(1, 2, "Fool"),
(2, 3, "PHB"),
(2, 4, "Software guru"),
(2, 5, "PFY"),
(3, 6, "Number cruncher");
CREATE TABLE `peeps` (`job_id` INTEGER NOT NULL,
`peep_name` varchar(32) NOT NULL);
INSERT INTO `peeps`(`job_id` , `peep_name` )
VALUES(1, "Smith"),
(2, "Jones Major"),
(2, "Jones Minor"),
(4, "Mr. In-the-wrong-department"),
(4, "Mawg"),
(5, "William Topaz McGonagall"),
(6, "Blaise Pascal"),
(6, "Isaac Newton");
因此,正如您所看到的,可以有一个或多个部门,每个部门可以由一个或多个人完成一个或多个工作。
这是一个整洁的树层次结构,我想返回它以响应一个AJAX请求,所以我有三个嵌套for循环,每个都发出一个SELECT
语句(coed不可用,因为它在家里和我我在办公室,但我相信你可以想象它;它很简单。)
我在客户端遇到了一些问题,尝试添加一个新的空白条目,it was suggested我应该停用一组对象as shown here。
但是,这仅显示在深度级别上,因此带SELECT
的单个while ($row = $stmt->fetch(PDO::FETCH_OBJ))
足以构建返回值 - 对象数组。
如何构建我的返回值,它将是一个对象数组数组的嵌套数组?
[更新]我删除了之前对小提琴的引用,因为它至少混淆了一个人。
我想返回一系列部门,每个部门包含该部门的数据,以及一系列工作,每个工作包含该工作的数据,以及执行该工作的一系列人员
[更新]这是一个容易50分的人。
他的SQL没有显示与departments
相关联的数据。我怀疑我只需要(INNER?) JOIN departments.*
。但确切的SQL命令是什么?
什么是PHP代码?我怀疑$result = $sqlQuery->fetchAll(PDO::FETCH_ASSOC);
或类似的
顺便说一句,SQL
有a fiddle我最好的努力只返回一个平面数组,而不是一个嵌套的树,如发布的答案所示: - (
[更新]感谢您的回答。为了帮助他人,我在http://phpfiddle.org/main/code/xfdj-wthc
发布了一个工作小提琴请注意,该解决方案支持多个外键,其中我只有一个。我可以简化代码供个人使用,但是感谢@trincot使它变得如此灵活,因为这可能对其他人有用。
答案 0 :(得分:2)
如果要输出树结构,则不需要使用循环。您只需进行以下查询:
SELECT p.`peep_name`, j.* FROM `peeps` p INNER JOIN `jobs` j ON j.job_id = p.job_id
将返回如下结构:
peep_name deperatment_id job_id job_name
Smith 1 1 Idiot
Jones Major 1 2 Fool
Jones Minor 1 2 Fool
Mr. In-the-wrong-department 2 4 Software guru
Mawg 2 4 Software guru
William Topaz McGonagall 2 5 PFY
Blaise Pascal 3 6 Number cruncher
Isaac Newton 3 6 Number cruncher
然后,您将能够以此格式输出此数据,或将此数据组合成所需格式的树结构。例如,您可以使用以下格式输出它:
{
"departments":
[
{
"ID": 1,
"jobs":
[
{
"ID": 1,
"Name": "Idiot"
"Peeps":
[
"Smith"
]
},
{
"ID": 2,
"Name": "Fool"
"Peeps":
[
"Jones Major",
"Jones Minor"
]
}
]
},
// etc.
]
}
答案 1 :(得分:1)
以下是一些代码,它们从单独的数组中的每个表中检索数据,然后从中构建最终的数据结构。
这是非常通用的,因为您只需为每对表指定哪些字段是公共密钥(主键和外键,假定它们具有相同的名称):
function loadTable($dbh, $table) {
// Perform simple table select, and return result set
$sth = $dbh->prepare("SELECT * FROM $table");
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}
function connectChildren($parents, $children, $name, $common_keys) {
/* Returns $parents array, but with each element extended with
* a $name key, which is an array of matching $children elements.
* The match is made by comparing the values for each of the $common_keys
* in both arrays.
* When a $children element is added to the $name array, its $common_keys
* are removed from it as they are already known in the $parents element.
* (this removal behaviour is optional and could be left out)
*/
$index = [];
// Build a temporary index to associate $parents elements by their
// primary key value (can be composite)
foreach ($parents as $i => $parent) {
$primary_key = [];
foreach ($common_keys as $common_key) {
$primary_key[] = $parent[$common_key];
}
$index[implode("|", $primary_key)] = $i;
$parents[$i][$name] = [];
}
// Main algorithm: inject $children into $parents
foreach($children as $child) {
$foreign_key = [];
// Collect foreign key value
foreach ($common_keys as $common_key) {
$foreign_key[] = $child[$common_key];
// Remove foreign key from child
unset($child[$common_key]);
}
// Find the corresponding $parents element via the index
$i = $index[implode("|", $foreign_key)];
$parents[$i][$name][] = $child;
}
return $parents;
}
// Step 1: load all the table data
$rows_dep = loadTable($dbh, "departments");
$rows_job = loadTable($dbh, "jobs");
$rows_peep = loadTable($dbh, "peeps");
// Step 2: connect the data, layer by layer, in bottom-up order:
$rows_job = connectChildren($rows_job, $rows_peep,
"peeps", ["deperatment_id", "job_id"]);
$rows_dep = connectChildren($rows_dep, $rows_job,
"jobs", ["deperatment_id"]);
print_r ($rows_dep);
测试数据的输出:
Array
(
[0] => Array
(
[deperatment_id] => 1
[department_name] => HR
[jobs] => Array
(
[0] => Array
(
[job_id] => 1
[job_name] => Idiot
[peeps] => Array
(
[0] => Array
(
[peep_name] => Smith
)
)
)
[1] => Array
(
[job_id] => 2
[job_name] => Fool
[peeps] => Array
(
[0] => Array
(
[peep_name] => Jones Major
)
[1] => Array
(
[peep_name] => Jones Minor
)
)
)
)
)
[1] => Array
(
[deperatment_id] => 2
[department_name] => Software
[jobs] => Array
(
[0] => Array
(
[job_id] => 4
[job_name] => Software guru
[peeps] => Array
(
[0] => Array
(
[peep_name] => Mr. In-the-wrong-department
)
[1] => Array
(
[peep_name] => Mawg
)
)
)
[1] => Array
(
[job_id] => 5
[job_name] => PFY
[peeps] => Array
(
[0] => Array
(
[peep_name] => William Topaz McGonagall
)
)
)
)
)
[2] => Array
(
[deperatment_id] => 3
[department_name] => Accounts
[jobs] => Array
(
[0] => Array
(
[job_id] => 6
[job_name] => Number cruncher
[peeps] => Array
(
[0] => Array
(
[peep_name] => Blaise Pascal
)
[1] => Array
(
[peep_name] => Isaac Newton
)
)
)
)
)
)
然后,您可以继续使用json_encode($departments)
等