1. Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm
    Information ausblenden

Join von 2 DB

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von scheffer, 1 September 2019.

  1. scheffer

    scheffer Neuer Benutzer

    Hallo,
    ich versuche zwei Tabellen über ein Join abzufragen, leider gelingt mir das nur bedingt.

    Hier mal die Infos zu den Tabellen:
    Tabelle 1: x_users mit "id, name, username, email"
    Tabelle 2: x_fields_values mit "field_id, item_id, value"

    Die Felder x_users.id und x_fields_values.item_id sind die die IDs der User, über die die Abfrage generiert wird.
    x_fields_value.field_id kann die Werte 1-17, wobei die die x_fields_value.value dann z.B. Vorname, Strasse, etc hat

    Hier ein Beispiel:
    Tabelle 1:
    id name username email
    1 Müller mueller mueller@gmx.de
    2 Schmidt schmidt schmidt@gmx.de

    Tabelle 2:
    field_id item_id value
    12 1 Peter
    13 1 Musterstrasse
    1 1 089-12345678
    12 2 Monika
    13 2 Ortgasse
    1 2 089-9876543

    Die Abfrage mache ich über:
    $sql = 'SELECT * FROM x_users INNER JOIN x_fields_values ON (x_users.id = x_fields_values.item_id) ORDER BY x_users.username ASC';
    und lasse mir dann in einer Tabelle die Ergenisse anzeigen:

    echo '<table border="1">';
    while ($row = $erg->fetch_assoc()) {
    // echo '"'.$row['id'].'" "'.$row['name'].'" "'.$row['username'].'" "'.$row['email']."\"<br />\n";
    echo "<tr>";
    echo "<td>". $row['id'] . "</td>";
    echo "<td>". $row['name'] . "</td>";
    echo "<td>". $row['username'] . "</td>";
    echo "<td>". $row['email'] . "</td>";
    echo "<td>". $row['value'] . "</td>";
    echo "</tr>";
    }
    echo "</table>";

    Das bewirkt aber, dass die Tabelle wir folgt aussieht:
    1 Müller mueller mueller@gmx.de Peter
    1 Müller mueller mueller@gmx.de Musterstrasse
    1 Müller mueller mueller@gmx.de 089-12345678
    2 Schmidt schmidt schmidt@gmx.de Monika
    2 Schmidt schmidt schmidt@gmx.de Monika
    2 Schmidt schmidt schmidt@gmx.de 089-9876543

    Ich hätte aber gerne:
    1 Müller mueller mueller@gmx.de Peter Musterstrasse 089-12345678
    2 Schmidt schmidt schmidt@gmx.de Monika Ortgasse 089-9876543


    Bin für jeden Tipp dankbar.


    VG
    rs
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Code:
    test=*# select * from x_users ;
     id |  name   | username |     email     
    ----+---------+----------+----------------
      1 | müller  | mueller  | mueller@gmx.de
      2 | schmidt | schmidt  | schmidt@gmx.de
    (2 rows)
    
    test=*# select * from x_fields_values ;
     field_id | item_id |    value     
    ----------+---------+--------------
           12 |       1 | peter
           13 |       1 | musterstraße
            1 |       1 | 08912345678
           12 |       2 | monika
           13 |       2 | ortsgasse
            1 |       2 | 0899876543
    (6 rows)
    
    test=*# select u.name, u.username, u.email, max(i.value) filter (where i.field_id = 12) as vorname,max(i.value) filter (where i.field_id = 13) as straße, max(i.value) filter (where i.field_id = 1) as telefon from x_users u left join x_fields_values i on (u.id=i.item_id) group by u.name, u.username, u.email;
      name   | username |     email      | vorname |    straße    |   telefon   
    ---------+----------+----------------+---------+--------------+-------------
     schmidt | schmidt  | schmidt@gmx.de | monika  | ortsgasse    | 0899876543
     müller  | mueller  | mueller@gmx.de | peter   | musterstraße | 08912345678
    (2 rows)
    
    test=*#
    
    PostgreSQL, für MySQL wirst das etwas anpassen müssen.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    Hier noch eine beim Feld telefon leicht andere Variante:

    Code:
    test=*# select u.name, u.username, u.email, max(i.value) filter (where i.field_id = 12) as vorname,max(i.value) filter (where i.field_id = 13) as straße, string_agg(case when i.field_id=1 then i.value else null end,'') as telefon from x_users u left join x_fields_values i on (u.id=i.item_id) group by u.name, u.username, u.email;
      name   | username |     email      | vorname |    straße    |   telefon   
    ---------+----------+----------------+---------+--------------+-------------
     schmidt | schmidt  | schmidt@gmx.de | monika  | ortsgasse    | 0899876543
     müller  | mueller  | mueller@gmx.de | peter   | musterstraße | 08912345678
    (2 rows)
    
    test=*#
    
    Gibt also, wie so oft, mehrere Möglichkeiten.
     
  4. scheffer

    scheffer Neuer Benutzer

    Vielen lieben Dank für die schnelle Hilfe. Leider führt das bei mir zu einem Fehler:

    Meldung:
    Etwas stimmte mit dem Query nicht: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(where i.field_id = 12) as vorname,max(i.value) filter (where i.field_id = 13) a' at line 1
    Ich nutze mein Testsystem unter MAMP (auf MAC) mit MySQL-Version: 5.7.26
    In echt läuft das System auf Betriebssystem: MySQL-Version: 5.6.42-log
    Du hast geschrieben: PostgreSQL, für MySQL wirst das etwas anpassen müssen.

    Könntest Du mir bitte einen Tipp geben, was ich für MySQL ändern muss ?

    Danke und VG
    rs
     
  5. akretschmer

    akretschmer Datenbank-Guru

    Also generell gesprochen funktioniert MySQL deutlich besser, wenn man es durch PostgreSQL ersetzt ;-)

    Die zweite Variante, also das "string_agg(case when i.field_id=1 then i.value else null end,'') as telefon", sollte sich mit MySQL einfacher machen lassen als die sehr elegante Variante mit FILTER ( ... ).
     
  6. akretschmer

    akretschmer Datenbank-Guru

    Hint: string_agg() ist eine Aggregatsfunktion. Es gibt was ähnliches in MySQL.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden