de.comp.lang.php.* FAQ

16.6. Wie kann ich zwei Tabellen miteinander verknüpfen?

Antwort von Kristian Köhntopp

Man kann dies mit Hilfe einer JOIN-Operation tun. Diese ist im Kapitel 7.20 des MySQL-Handbuches beschrieben.

Wenn die Tabellen artikel und email als Primärschlüsselfelder artikel.KundenID und email.eid haben und artikel mit email über den Fremdschlüssel email.KundenID verknüpft ist, dann kann man einen Equi-JOIN mit dem folgenden Statement formulieren:

mysql> select * from artikel;
+----------+
| KundenID |
+----------+
|        1 |
|        2 |
|        3 |
+----------+
3 rows in set (0.00 sec)

mysql> select * from email;
+-----+----------+
| eid | KundenID |
+-----+----------+
|   1 |        1 |
|   2 |        2 |
|   3 |        3 |
+-----+----------+
3 rows in set (0.00 sec)

mysql> select a.KundenID as aid,
     >        e.eid as eid,
     >        e.KundenID as e_aid
     >   from artikel as a,
     >     email as e
     > where a.KundenID = e.KundenID;
+-----+-----+-------+
| aid | eid | e_aid |
+-----+-----+-------+
|   1 |   1 |     1 |
|   2 |   2 |     2 |
|   3 |   3 |     3 |
+-----+-----+-------+
3 rows in set (0.01 sec)

In keinem Fall können in den herangejointen Tabellen Nullwerte enthalten sein.

Diese Operation ist dann effizient, wenn a.KundenID und t.KundenID denselben Typ haben, und auf auf a.KundenID und t.KundenID ein UNIQUE INDEX oder ein INDEX liegen. In MySQL ist ein PRIMARY KEY immer auch ein UNIQUE INDEX.

Wenn man optionale Werte hat, dann kann man keinen symmetrischen Join (Equijoin) mehr machen, sondern muss einen asymmetrischen Join (Left Join) durchführen. Dadurch können auf der rechten Seite Nullwerte entstehen:

mysql> select * from telefon;
+-----+----------+
| tid | KundenID |
+-----+----------+
|   1 |        1 |
|   2 |        3 |
+-----+----------+
2 rows in set (0.00 sec)


Equijoin (es fehlt KundenID 2, weil keine
Telefonnummer definiert ist):

mysql> select a.KundenID as aid,
     >        e.eid as eid,
     >        e.KundenID as e_aid,
     >        t.tid as tid,
     >        t.KundenID as t_aid
     >   from artikel as a,
     >        email as e,
     >        telefon as t
     > where a.KundenID = e.KundenID
     > and a.KundenID = t.KundenID;
+-----+-----+-------+-----+-------+
| aid | eid | e_aid | tid | t_aid |
+-----+-----+-------+-----+-------+
|   1 |   1 |     1 |   1 |     1 |
|   3 |   3 |     3 |   2 |     3 |
+-----+-----+-------+-----+-------+
2 rows in set (0.02 sec)


Left Join (generiert Nullwerte):

mysql> select a.KundenID as aid,
     >        t.tid as tid,
     >        t.KundenID as t_aid
     >   from artikel as a left join telefon as t
     >        on a.KundenID = t.KundenID;
+-----+------+-------+
| aid | tid  | t_aid |
+-----+------+-------+
|   1 |    1 |     1 |
|   2 | NULL |  NULL |
|   3 |    2 |     3 |
+-----+------+-------+
3 rows in set (0.00 sec)


Unterschiedliche Counts:

mysql> select count(a.KundenID) as acount,
     >        count(t.KundenID) as tcount
     >   from artikel as a left join telefon as t
     >        on a.KundenID = t.KundenID;
+--------+--------+
| acount | tcount |
+--------+--------+
|      3 |      2 |
+--------+--------+
1 row in set (0.01 sec)

Die Tabelle a ist hier die aufspannende Tabelle, die Tabelle t ist die aufgespannte Tabelle. An den Stellen, an denen t keine zu a passenden Werte hat, tauchen Nullwerte in t auf. Da die Relation nun nicht mehr symmetrisch ist, muss man zwischen a.KundenID und t.KundenID unterscheiden. Insbesondere sind die count()-Werte beider Spalten unterschiedlich.

Da a.KundenID und t.KundenID unterschiedlich sind, muss man auch zwingend mit qualifizierten Namen arbeiten und kann nicht mehr einfach KundenID schreiben.

Ein gemischter Join verwendet Equijoins und Left Joins, wie es gerade passt:

mysql> select a.KundenID as aid,
     >        e.eid as eid, e.KundenID as e_aid,
     >        t.tid as tid, t.KundenID as t_aid
     >   from artikel as a,
     >        email as e left join telefon as t
     >        on a.KundenID = t.KundenID
     >  where a.KundenID = e.KundenID;
+-----+-----+-------+------+-------+
| aid | eid | e_aid | tid  | t_aid |
+-----+-----+-------+------+-------+
|   1 |   1 |     1 |    1 |     1 |
|   2 |   2 |     2 | NULL |  NULL |
|   3 |   3 |     3 |    2 |     3 |
+-----+-----+-------+------+-------+
3 rows in set (0.01 sec)

Valid HTML 4.01! Valid CSS!

16.6. Wie kann ich zwei Tabellen miteinander verknüpfen?
http://www.php-faq.de/q/q-sql-join.html
Archiv der de.comp.lang.php-FAQ Dies ist eine Archivseite von 2008 und wurde seitdem nicht geändert. Das dclp-FAQ-Team