SQL将数据连接到多维数组

时间:2016-11-04 12:19:29

标签: php mysql oop multidimensional-array

我已经解决了这个问题了一段时间我现在有一个手动过程,我将数据构建成我想要的数组格式,但我发现它耗费时间并且很容易破解。

所以我尽力自动完成以下任务。

例如,我的数据库中有2个表,users表和addresses表。

users表与addresses表具有一对多的关系。

我使用查询来下载数据以连接表并下拉每一行,例如查询:

SELECT users.name AS 'users.name',
       users.age AS 'users.age',
       addresses.street AS 'users.addresses.street',
       addresses.suburb AS 'users.addresses.suburb'

    JOIN addresses ON 
    users.user_id = addresses.user_id

FROM users;

如果我有2个用户,一个有2个地址,另一个有3,那么它应该返回5行:

  

|的 users.name |的 users.age |的 users.addresses.street |的 users.addresses.suburb |

     

约书亚| 28 | 3假St |悉尼

     

约书亚| 28 | 16新St |悉尼

     

约书亚| 28 | 140 Apple St |悉尼

     蒂姆| 34 |约翰街18号悉尼

     蒂姆| 34 | 143 Clark St |悉尼

将结果作为关联数组获取将返回如下数组中的结果:

array( 
    'users.name' => 'Joshua',
    'users.age' => 28,
    'users.addresses.street' => '3 Fake St',
    'users.addresses.state' => 'Sydney'
),
array( 
    'users.name' => 'Joshua',
    'users.age' => 28,
    'users.addresses.street' => '16 New St',
    'users.addresses.state' => 'Sydney'
),
array( 
    'users.name' => 'Joshua',
    'users.age' => 28,
    'users.addresses.street' => '140 Apple St',
    'users.addresses.state' => 'Sydney'
),
array( 
    'users.name' => 'Tim',
    'users.age' => 34,
    'users.addresses.street' => '18 John St',
    'users.addresses.state' => 'Sydney'
),
array( 
    'users.name' => 'Tim',
    'users.age' => 34,
    'users.addresses.street' => '143 Clark St',
    'users.addresses.state' => 'Sydney'
)

我想用上面的数组做的是将每个结果行转换成多维数组,如下所示:

array (
    'users' => array(
        'name' = > 'Joshua',
        'age' => 28,
        'addresses' => 
            array(
                'street' =>  '3 Fake St',
                'state' => 'Sydney'      
            ),
            array(
                'street' =>  '16 New St',
                'state' => 'Sydney'      
            ),
            array(
                'street' =>  '140 Apple St',
                'state' => 'Sydney'      
            )
    ),
),
array (
    'users' => array(
        'name' = > 'Tim',
        'age' => 44,
        'addresses'' => 
            array(
                'street' =>  '18 John St',
                'state' => 'Sydney'      
            ),
            array(
                'street' =>  '143 Clark St',
                'state' => 'Melborune'      
            )
    ),
)

正如您所看到的,数据库返回的数组键中的每个句点都应该展开,然后转换为多维数组,最后一个展开的键应该是键值。

我使用数组提取和一些疯狂检查来完成此操作,只获取某些键名并将它们放入数组中然后我使用array_map构建数组结构......但对于大型数据集来说这非常繁琐并且必须手动写出每个关系并将其全部映射到我认为是愚蠢的。

我一直试图建立一些符合上述描述但没有运气的东西,因此我现在就在这里。

注意

以上是一组数据的示例,我正在尝试创建它,以便可以使用多组数据轻松完成,而不必编写循环并手动创建多维数组。

2 个答案:

答案 0 :(得分:1)

你可以做一些更通用的事情

$records = array(
    array(
        'user.name' => 'Joshua',
        ....
    ),
);


$result = [
    'users' => []
];

foreach ( $records as $r ) {
    $new_record = [];
    foreach ( $r as $k => $v ) {
        $parsed = explode('.', $k);
        $cur    = &$new_record;
        for ( $i = 1, $n = count($parsed); $i < $n - 1; $i ++ ) {
            if ( ! isset($cur[ $parsed[ $i ] ]) ) {
                $cur[ $parsed[ $i ] ] = [ ];
            }
            $cur = &$cur[ $parsed[ $i ] ];
        }
        $cur[ $parsed[ $i ]] = $v;
    }
    $result['users'][] = $new_record;
}

print_r($result);

这里我们为每个用户记录创建一个新的$new_record,并使用当前嵌套级别的引用。

注意:在这种情况下,我把所有用户放在同一个数组中。您可以在每条记录中包含users索引,只需进行一些修改:

$result = [];

foreach ( $records as $r ) {
    $new_record = [];
    foreach ( $r as $k => $v ) {
        $parsed = explode('.', $k);
        $cur    = &$new_record;
        for ( $i = 0, $n = count($parsed); $i < $n - 1; $i ++ ) {
            if ( ! isset($cur[ $parsed[ $i ] ]) ) {
                $cur[ $parsed[ $i ] ] = [ ];
            }
            $cur = &$cur[ $parsed[ $i ] ];
        }
        $cur[ $parsed[ $i ]] = $v;
    }
    $result[] = $new_record;
}

这将为您提供您所要求的确切结构

答案 1 :(得分:0)

我认为输出的最大问题是数组没有索引,因此很难甚至无法检测和删除重复项。像array_unique()这样的函数将无法正常工作。在这里,您有一个带有索引输出的foreach解决方案,希望它有所帮助:

<?php
//given the result of the fetch()
$inputData = array(array(
    'users.name'             => 'Joshua',
    'users.age'              => 28,
    'users.addresses.street' => '3 Fake St',
    'users.addresses.state'  => 'Sydney'
),
    array(
        'users.name'             => 'Joshua',
        'users.age'              => 28,
        'users.addresses.street' => '16 New St',
        'users.addresses.state'  => 'Sydney'
    ),
    array(
        'users.name'             => 'Joshua',
        'users.age'              => 28,
        'users.addresses.street' => '140 Apple St',
        'users.addresses.state'  => 'Sydney'
    ),
    array(
        'users.name'             => 'Tim',
        'users.age'              => 34,
        'users.addresses.street' => '18 John St',
        'users.addresses.state'  => 'Sydney'
    ),
    array(
        'users.name'             => 'Tim',
        'users.age'              => 34,
        'users.addresses.street' => '143 Clark St',
        'users.addresses.state'  => 'Sydney'
    ));

//The result
$result = [];
//The first key
$result['users'] = [];
//Flatten the array with name and age
foreach ($inputData as $registries => $registry) {
    //add the data or overwritte it if exists
    $result['users'][$registry['users.name']] = ['name'      => $registry['users.name'],
                                                 'age'       => $registry['users.age'],
        //If you have any addresses info, keep it, otherwise declare an empty array
                                                 'addresses' => is_array($result['users'][$registry['users.name']]) && array_key_exists('addresses', $result['users'][$registry['users.name']]) ? $result['users'][$registry['users.name']]['addresses'] : []
    ];

    //if the current address is not in the list, add it
    if (!array_key_exists($registry['users.addresses.street'], $result['users'][$registry['users.name']]['addresses']))
        $result['users'][$registry['users.name']]['addresses'][$registry['users.addresses.street']] = ['street' => $registry['users.addresses.street'], 'state' => $registry['users.addresses.state']];

}
//Dump the result, move this inside the foreach() to get a dump for each user. Redeclare $result if every user has to be output separately
print_r($result);