GZs*_*dio 0 php mysql arrays multidimensional-array
我有共同的情况,但我找不到共同的解决方案......
想象一下我有两个表,如作者和相应的书籍:
作者
+----+-----------+
| id | name |
+----+-----------+
| 1 | O.Connor |
| 2 | F.Myler |
+----+-----------+
Run Code Online (Sandbox Code Playgroud)
图书
+----+-----------+-----------+----------------+
| id | author_id | title | number_of_pages|
+----+-----------+-----------+----------------+
| 1 | 1 |Book 1 |315 |
| 2 | 1 |Book 2 |265 |
+----+-----------+-----------+----------------+
Run Code Online (Sandbox Code Playgroud)
我想在一个sql查询中从数据库获取数据(我使用mySQL,但这并不重要,我想要一个独立于数据库的解决方案),使用JOIN,例如:
SELECT A.*, B.title as book_title, B.number_of_pages as book_pages FROM authors A LEFT JOIN books B ON B.author_id=A.id
Run Code Online (Sandbox Code Playgroud)
由于大型数据库的生产力问题,我想避免循环中的多个查询。然后我需要将第二个表中的数据嵌套为子数组,以避免拥有相同数据的多个副本。换句话说,我需要将数据库的平面结果转换为嵌套的多维数组。它应该给出类似的内容:
[
{
"id": 3,
"name": "O.Connor",
"birth_date": "05.06.1985",
"from": "England",
"mother": "",
"father": "",
"email": "email@example.com",
"books": [
{
"title": "Some Title",
"pages": 235
},
{
"title": "Some Title",
"pages": 267
},
{
"title": "Some Title",
"pages": 317
},
{
"title": "Some Title",
"pages": 235
},
{
"title": "Some Title",
"pages": 298
}
]
},
{
"id": 28,
"name": "O.Henri",
"birth_date": "05.06.1300",
"from": "England",
"mother": "",
"father": "",
"email": "email@example.com",
"books": [
{
"title": "Some Title",
"pages": 235
},
{
"title": "Some Title",
"pages": 267
},
{
"title": "Some Title",
"pages": 317
},
{
"title": "Some Title",
"pages": 235
},
{
"title": "Some Title",
"pages": 298
}
]
}
]
Run Code Online (Sandbox Code Playgroud)
到目前为止我找到的唯一相关资源是:
https://phpdelusions.net/pdo_examples/nested_array
第一个使用多个查询或一些 MySQL 中不可用的 SQL Server 功能。第二个建议分别从结果中获取每一行并即时构建结果数组。也许这不是一个糟糕的解决方案,但也许有更好、更高效的解决方案。
PDO 中有一些获取模式,例如 FETCH_GROUP 等。但对于我的任务来说,没有什么足够的。
我编写了自己的函数,其想法是进一步创建一些数据库类并将此函数作为方法插入(因此对于大多数情况来说它应该是真正通用的)。
function group_by($array, $criterias=NULL, $group_name='group') {
if ($criterias == NULL) return $array; // add also a verification of type
// transform input parameters for array_diff_key()
$criterias = array_flip($criterias);
$group = array($group_name=>0);
$result_array = [];
$push_index = 0;
foreach ($array as $row) {
$sup_array = array_diff_key($row, $criterias);
$sub_array = array_intersect_key($row, $criterias);
// add verification of not NULL elements in future
$isInArray = false;
foreach ($result_array as $index => $grouped_array) {
// if there is no difference between arrays then this sub-array is already present in a result array.
$array_without_groups = array_diff_key($grouped_array, $group);
if ( empty(array_diff_assoc($array_without_groups, $sup_array)) && (count($array_without_groups)==count($sup_array)) ) {
$isInArray = true;
$push_index = $index;
break;
}
}
if ($isInArray) {
array_push($result_array[$push_index][$group_name], $sub_array);
} else {
$sup_array[$group_name] = array();
array_push($sup_array[$group_name], $sub_array);
array_push($result_array, $sup_array);
}
}
return $result_array;
}
Run Code Online (Sandbox Code Playgroud)
然后你在 fetchAll 结果上调用它:
$result = group_by($result, array('book_title', 'book_pages'), 'books');
Run Code Online (Sandbox Code Playgroud)
我不认为这是最好的解决方案。我是 PHP 新手,所以我什至不确定我使用的 array_diff 和 array_intersect 是否是从另一个数组中提取一个数组的有效方法。我将不胜感激任何建议。
这是一个适用于 MySQL 5.7 或更高版本的解决方案。
SELECT A.id, A.name, A.birth_date, A.`from`, A.mother, A.father, A.email,
JSON_ARRAYAGG(JSON_OBJECT('title', B.title, 'pages', B.number_of_pages)) AS books
FROM authors A LEFT JOIN books B ON B.author_id=A.id
GROUP BY A.id;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1932 次 |
| 最近记录: |