Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用联接从单个查询中获取嵌套数组_Php_Mysql_Arrays_Multidimensional Array - Fatal编程技术网

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;