Php 使用联接从单个查询中获取嵌套数组
我有共同的情况,但我找不到共同的解决方案 假设我有两个表格,如作者和相应的书籍: 作者Php 使用联接从单个查询中获取嵌套数组,php,mysql,arrays,multidimensional-array,Php,Mysql,Arrays,Multidimensional Array,我有共同的情况,但我找不到共同的解决方案 假设我有两个表格,如作者和相应的书籍: 作者 +----+-----------+ | id | name | +----+-----------+ | 1 | O.Connor | | 2 | F.Myler | +----+-----------+ 书 我想在一个sql查询中从数据库获取数据(我使用mySQL,但没关系,我希望有一个独立于数据库的解决方案),使用JOIN,比如: SELECT A.*, B.title as bo
+----+-----------+
| id | name |
+----+-----------+
| 1 | O.Connor |
| 2 | F.Myler |
+----+-----------+
书
我想在一个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
我希望避免在一个循环中出现多个查询,因为大型数据库上存在生产力问题。然后我需要将第二个表中的数据嵌套为子数组,以避免相同数据的多个副本。换句话说,我需要将一个平面结果从数据库转换为一个嵌套的多维数组。它应该给出如下信息:
[
{
"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
}
]
}
]
到目前为止,我找到的唯一相关资源是:
第一种方法使用多个查询或MySQL中不可用的SQL Server功能。第二种方法建议分别从结果中获取每一行,并在运行中构造结果数组。也许这不是一个坏的解决方案,但也许有更好的、更高效的解决方案
PDO中有一些fetch模式,如fetch_组等,但对于我的任务来说,什么都不够
我写了自己的函数,打算进一步创建一些DB类,并将此函数作为一个方法插入(因此在大多数情况下它应该是真正通用的)
然后在fetchAll结果中调用此函数,如下所示:
$result = group_by($result, array('book_title', 'book_pages'), 'books');
我认为这不是最好的解决办法。我是PHP的高手,所以我甚至不确定我使用的数组diff和数组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;
使用author ID作为结果数组的键,然后可以轻松地收集该数组下的相关数据。(您可以在以后对整个结果使用
array_values
,将这些键“重置”为一个简单的、基于零的索引。)这项任务并不难,只需要精确性。为所有表提供一个示例-创建表,插入到包含示例数据(每个表3-5行)和所需输出(MySQL输出,而不是其在PHP上的表示形式)的中。还要指定精确的MySQL版本。是否有一些在线资源有助于快速创建一个示例?答案中对此有一些很好的说明。我认为您担心单个查询会重复每本书的作者信息,因为SQL只处理矩形数据表。我猜你担心那些额外重复作者信息是浪费。别担心。认真地数据库系统为此进行了优化。你的代码格式的东西是好的。多个查询比结果集中的一些冗余信息浪费得多。非常感谢!我读过关于这个函数的文章。问题是我维护的项目使用MySQL 5.6。由于遗留代码和缺乏时间(和金钱:)可能是我发明了轮子,但我想编写这样的函数来完成所有工作。请您将它重新布线一点,也许您可以提出一些改进。谢谢。如果您仍然使用MySQL 5.6,解决方法就是O.Jones在上面的评论。按原样获取数据,并在获取数据后在应用程序代码中重新格式化。如果您认为升级到MySQL 5.7太耗时和昂贵,请想象一下用SQL编写和维护格式化JSON所需的意大利面代码会有多昂贵。别这样!
$result = group_by($result, array('book_title', 'book_pages'), 'books');
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;