2016-11-04 77 views
2

我一直在这个问题上有一段时间,现在有一个手动过程,我将数据构建成我想要的数组格式,但是我发现它非常耗时且非常容易打破。SQL将数据加入到多维数组中

所以我试图自动化以下任务,尽我所能。例如,我在我的数据库中有两个表格,一个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 |

Joshua | 28 | 3假St |悉尼

Joshua | 28 | 16新St |悉尼

Joshua | 28 | 140 Apple St |悉尼

Tim | 34 | 18约翰St |悉尼

Tim | 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构建数组结构...但它对于大数据集和单调乏味不得不手动写出每一个关系,并将其映射到一切都是愚蠢的,我认为。

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

以上是针对一组数据的一个例子,我试图创建此,因此它可以很容易地与多组数据的完成,不必写一个循环和手动创建多维数组。

+0

这些都是真的不同寻常的别名 – Strawberry

+0

嗯,我玩了确切的结构和试图使用别名来帮助构建数组关联。我完全接受建议。我只是有一种感觉,我错过了我错过的难题的重要部分。希望有人可以引发一些想法或线索,我错过了或在思考 – joshualawson

+0

嗯 - 这只是一个简单的PHP循环。我会写出一个解决方案,但是我在PHP中操作数组其实很糟糕 - 但有数千个例子。但我不会包含'。'在别名中。我认为这只是要求麻烦, – Strawberry

回答

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为每个用户记录,并使用当前嵌套级别的参考。

注意:在这种情况下btw我把所有的用户在同一个数组。你可以在每个记录内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; 
} 

这会给你,你所要求

+0

这几乎就在那里,并且在正确的路径上!我会稍微修改一下,并在今晚晚些时候发布我的结果。目前,您的示例将它们格式化为每个用户的新数组元素,而不是匹配用户并将地址添加到地址数组中。但它的完美! – joshualawson

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);