# Zusammenführen von MYSQL Datensätzen mit PHP und GROUP_CONCAT - Problem



## pekudel (10. April 2013)

Hallo!

Ich muss zwei Tabellen in einer MYSQL Datenbank zusammenführen.

Die Tabellen so in etwa aus:

Tabelle 1 (hat 16000 Einträge)

idnameprodukt_ids1produkt 139120,38129,38127,381912produkt 284798,21003,66191,38991

Tabelle 2 ( Hat 45000 Einträge)

idproduct_idseriennummer139120sn1,sn2,sn3238129sn4,sn5,sn6238129sn7,sn8,sn9


Aussehen soll das ganze so:

idnameseriennummer1produkt 1sn1,sn2,sn3,...2produkt 2sn7,sn8,sn9,...

*Zu Erklärung*
Die Spalte "product_ids" in Tabelle 1 enhält (kommagetrennt!) die Schlüssel zu den Seriennummern in der Tabelle 2. product_ids können in den einzelnen Zeilen der Tabelle 1 ident sein - dh. im Datensatz 500 kann product_id 5600 vorkommen, im Datensatz 654 kann product_id 5600 auch vorkommen.
In der Tabelle 2 können meherere Zeilen bzw. Datensätze zu product_id (z.B.) 5600 vorkommen.

*Mein Problem*
Ich benötige nun ein Script oder eine MYSQL-Funktion, die mir zu jedem Datensatz der Tabelle 1 die Seriennummern aus Tabelle 2 sucht und in einer weiteren Spalte der Tabelle 1 (z.B. "Seriennummer") kommagetrennt zusammensetzt. Sprich wenn in der Tabelle zu einer "product_id" beispielsweise mehrere Datensätze vorhanden sind, sollen diese zusammengeführt werden und kommagetrennt in eine spezielle Spalte der Tabelle 1 eingetragen werden.


*Ansätze zur Problemlösung*
Habe mit GROUP_CONCAT und einer Schleife ein Script erstellt, welches als erstes alle doppelten Datensätze aus Tabelle 2 zusammenführt. Danach wird jeder Datensatz in Tabelle 1 aufgerufen, mittels foreach die Spalte product_ids aufgelöst (damit ich jede product_id einzeln erhalte) und frage mit einer funktion dann die Zeile in der Tabelle 2 ab, welche die gesuchte product_id enthält.


*Leider dauert es knapp 10 das Script auszuführen (trotz schnellem Server). Zudem stimmen manche Zeilen nicht dh. es werden product_ids ausgelassen. 
Habt ihr eine Lösugn für mich? Ein VIEW mit mysql? Eine direkte MYSQL Funktion? Oder eine Idee für ein PHP-Script?

Bin verzweifelt  *


----------



## Yaslaw (10. April 2013)

Gibt es auch eine Tabelle mit den seriennummer? Also pro seriennummer eine eigene Zeile? Das würde es enorm vereinfachen.

Ansonsten kommst du fast nicht auf einen grünen Zweig


----------



## pekudel (10. April 2013)

Nein gibt es nicht. Aber ich könnte eine Tabelle erstellen, in der für jede Seriennummer eine Zeile gibt.
Soll heißen ich ändere meine "Tabelle 2".
Schaut dann so aus:
id | product_id | seriennummer
1  | 123 | A
1 | 123 | B
1 | 200 | C
...


Würde das etwas bringen?


----------



## Yaslaw (10. April 2013)

Oh ja! Normalisieren ist immer gut. Das vereinfacht das ganze immens

Etwa so könnte es dann gehen

```
SELECT
    tbl_1.id,
    tbl_1.name,
    GROUP_CONCAT(DISTINCT tbl_2.seriennummer ORDER BY tbl_2.seriennummer DESC SEPARATOR ',') AS sn_list
FROM
    tbl_2,
    tbl_1
WHERE
    FIND_IN_SET(tbl_2.product_id, tbl_1.produkt_ids)
GROUP BY
    tbl_1.id,
    tbl_1.name
```

Merke dir. ID-Listen mit Kommas getrennt sind immer unpraktisch und unperformant. Wass man kann sollte man normalisieren. Sprich pro Nr eine Zeile. Dann kann SQL gut arbeiten.

Auch deine tabelle 1 sollte man normailsieren. Würde dir in Zukunft einige Probleme wegnehmen.
Also einfache eine Zuordnungstabelle machen wo pro tbl_1.id und passender produkt_id ein Eintrag drin ist.

siehe auch http://wiki.yaslaw.info/wikka/MySqlNormalizeFormSet


----------



## pekudel (10. April 2013)

Vielen Dank! Werde das ganze heute Nacht ausprobieren!!
Danke auch für deinen Link ...werde versuchen auch Tabelle 1 zu normalisieren.

Das Problem ist, das ich die Daten schon so bekomme, müsste also immer nachträglich normalisieren. Werde das ausprobieren.

Einstweilen vielen Dank )


----------



## Yaslaw (10. April 2013)

Hier noch ein kleines PHP-Script um die Seriennummern zu normalisieren. Natürlich ungetestet.

Annahnme: Die Zuordnungstabelle heisst sn_zuo und hat die Felder produkt_id und seriennummer

```
$sql = 'SELCT produkt_id, seriennummer FROM tbl_2';
$result = mysql_query($sql);

$zuoInserts = array();

//Pro Eintrag...
while($row = mysql_fetch_assoc($result)){
    //und pro Serienennummer
    foreach(explode($row['seriennummer']) as $sn){
        //Die Value-Liste für einen INSERT zusammensetzen
        $insertValues = sprintf("(%d, '%s')", $row['produkt_id'], $sn);
        //Prüfen ob die Kombination schon vorhanden ist um Doppelte EInträge zu verhindern
        if(!in_array($insertValues, $zuoInserts)){
            //Wenn nicht, in den Array eintragen
            $zuoInserts[] = $insertValues;    
        }        
    }
}

//Alle Inserts des Array ausführen
$sql = "INSERT INTO sn_zuo (produkt_id, seriennummer) VALUES " . implode(',', zuoInserts);
mysql_query($sql);
```


----------

