2016-11-04 1 views
2

Ich habe auf dieses Problem seit einer Weile, jetzt habe einen manuellen Prozess, den ich tun, um die Daten in das Array-Format, das ich will, aber ich finde es zeitaufwendig und sehr einfach zu tun Unterbrechung.SQL Joined Daten in mehrdimensionalen Array

Also versuche ich die folgende Aufgabe so gut wie möglich zu automatisieren. Als Beispiel habe ich zwei Tabellen in meiner Datenbank, eine users Tabelle und eine addresses Tabelle.

Die users Tabelle hat eine Eins-zu-viele-Beziehung mit der Tabelle addresses.

ich nach unten ziehe meine Daten eine Abfrage unter Verwendung der Tabellen zu verknüpfen und ziehen Sie jede Zeile, zB Abfrage:

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; 

Wenn ich 2 Benutzer habe eines mit 2-Adressen und einen mit 3 sollte es 5 Zeilen zurückgeben wie folgt:

| benutzer.name | users.age | users.addresses.street | users.addressesvorwahl |

Joshua | 28 | 3 Gefälschte St Sydney

Joshua | 28 | 16 neue St | Sydney

Joshua | 28 | 140 Apfel St Sydney

Tim | 34 | 18 John St Sydney

Tim | 34 | 143 Clark St |

Sydney

Fetching die Ergebnisse als assoziatives Array würde die Ergebnisse in einem Array wie die Rückkehr folgenden:

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

Was ich will, dann mit der obigen Anordnung zu tun ist, jede Ergebniszeile in ein mehrdimensionales drehen Array wie folgt:

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'  
      ) 
    ), 
) 

wie Sie jede Periode in der Array-Schlüssel der Datenbank zurückkehrt sollte aufgelöst werden sehen können, wandte sich dann in das mehrdimensionale Array und die letzte explodierte Schlüssel sollte die sein Schlüsselwert.

Ich habe dies mit Array Fetch und einige verrückte Überprüfung, die nur bestimmte Schlüsselnamen bekommt und fügt sie in ein Array, dann verwende ich Array_map, um die Array-Struktur zu bauen ... Aber es ist ziemlich langweilig für große Datensätze und jede Beziehung manuell schreiben zu müssen und alles zu kartieren ist albern, denke ich.

Ich habe versucht, etwas aufzubauen, das meiner obigen Beschreibung entspricht, aber ohne Glück, weshalb ich jetzt hier bin.

HINWEIS

Die oben ist ein Beispiel für einen Satz von Daten, Ich versuche, diese so zu schaffen, es leicht mit mehreren Sätzen von Daten durchgeführt werden kann und nicht mit einer Schleife zu schreiben und manuell erstellen das multidimensionale Array aus.

+0

Das ist wirklich ungewöhnlich Aliase – Strawberry

+0

Nun, ich spiele mit ihm um und versuchen, die Aliase zu verwenden, um beim Aufbau der Array-Verknüpfungen zu helfen. Ich bin total offen für Vorschläge. Ich habe einfach das Gefühl, dass ich einen wichtigen Teil des Puzzles vermisse, den ich vermisse. Hoffe, jemand kann einige Ideen oder Hinweise zünden, die ich vermisse oder über/unter denke – joshualawson

+0

Nun - es ist nur eine einfache PHP-Schleife. Ich würde eine Lösung schreiben, aber ich bin wirklich schrecklich darin, Arrays in PHP zu manipulieren - aber es gibt Tausende von Beispielen. Aber ich würde '.' in einem Alias. Ich denke, es ist nur um Ärger zu bitten, – Strawberry

Antwort

1

Sie etwas tun können allgemeinere

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

Hier haben wir ein neues $new_record für jeden Benutzerdatensatz erstellen, und mit einem Referenz für die aktuelle verschachtelte Ebene.

HINWEIS: In diesem Fall btw ich alle Benutzer in das gleiche Array. Sie können mit einer kleinen Änderung in jedem Datensatz den users Index:

$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; 
} 

Dies gibt Ihnen die genaue Struktur, die Sie angefordert haben

+0

Dies ist fast da und auf dem richtigen Weg sicher! Ich werde ein bisschen daran basteln und später meine Ergebnisse veröffentlichen. Im Moment formatieren Ihre Beispiele sie in ein neues Array-Element für jeden Benutzer, anstatt den Benutzer zu vergleichen und die Adresse zum Adress-Array hinzuzufügen. Aber es ist perfekt! – joshualawson

0

Ich denke, das schlimmste Problem mit Ihrer Ausgabe ist, dass das Array nicht indiziert ist, so dass es sehr schwierig oder sogar unmöglich ist, Duplikate zu erkennen und zu entfernen. Funktionen wie array_unique() funktionieren nicht richtig. Hier finden Sie eine foreach-Lösung mit einer indexierten Ausgang haben, hoffe, es hilft:

<?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); 
Verwandte Themen