2016-11-04 78 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);