Mailinglisten-Archive |
LEFT JOIN Es ist nicht leicht zu verstehen, wie ein JOIN funktioniert. Daher erkläre ich das Ganze mal an einem Beispiel: Ich habe eine Tabelle "user" und eine andere Tabelle "note". Die Tabellen sind über das Feld "uid" (userid) logisch miteinander verbunden - so etwas wir ein foreign key gibt es in MySQL nicht. Im Laufe der Jahre sind Benutzer hinzugekommen, haben Notizen angelegt und sind dann irgendwann mal über eine Routine gelöscht worden. Und jetzt stellen wir fest, daß die Routine fehlerhaft war, und es noch massig Notizen gibt, für die es keinen Benutzerdatensatz mehr gibt. Jetzt will ich einen Gültigkeitsprüfer bauen, der folgendes macht: "Suche alle Notizen, für die es keinen Benutzerdatensatz mehr gibt." Legen wir die ganze Struktur doch mal an: create database test; use test; create table user ( uid integer unsigned not null auto_increment, # user-id unique cart_pkey1 (uid) ); create table note ( nid integer unsigned not null auto_increment, # note-id uid integer unsigned not null, # user-id content text, unique aic_pkey1 (nid) ); insert into user (uid) values (1111),(2222),(3333),(4444); insert into note (nid,uid) values (1,1111),(2,1111),(3,2222),(4,3333),(6,5555); select * from user; select * from note; Jetzt müßte folgendes da stehen: +------+ | uid | +------+ | 1111 | | 2222 | | 3333 | | 4444 | +------+ +-----+------+---------+ | nid | uid | content | +-----+------+---------+ | 1 | 1111 | NULL | | 2 | 1111 | NULL | | 3 | 2222 | NULL | | 4 | 3333 | NULL | | 6 | 5555 | NULL | +-----+------+---------+ Also hat die Notiz mit der nid 6 keinen passenden Datensatz in der Tabelle "user", da die uid in "note" ja 5555 ist und es keinen Datensatz in der Tabelle "user" mit uid 5555 gibt. Das immer von Hand zu machen ist nicht gut. Daher wollen wir ein Select bauen, was und da hilft. Meine erste Idee war: select user.uid from user, note where user.uid!=note.uid; +------+ | uid | +------+ | 2222 | | 3333 | | 4444 | | 2222 | | 3333 | | 4444 | | 1111 | | 3333 | | 4444 | | 1111 | | 2222 | | 4444 | | 1111 | | 2222 | | 3333 | | 4444 | +------+ Ging voll in die Hose. Aber wie dann? Der Trick ist dieser: Mit einem LEFT JOIN verbinden wir die Tabellen "user" und "note" über das Feld uid. Es wird für jede Notiz mindestends ein Datensatz erzeugt. Die Felder des passenden Users werden dann angehängt. Gibt es keinen passenden User, so werden die Werte mit NULL gefüllt. Gibt es mehrere User einer Notiz (nicht in diesem Beispiel), so würde für jeden passenden User ein Datensatz angelegt werden und die Feldwerte der Notiz würden wiederholt werden. "select * from note left join user on note.uid=user.uid;" +-----+------+---------+------+ | nid | uid | content | uid | +-----+------+---------+------+ | 1 | 1111 | NULL | 1111 | | 2 | 1111 | NULL | 1111 | | 3 | 2222 | NULL | 2222 | | 4 | 3333 | NULL | 3333 | | 6 | 5555 | NULL | NULL | +-----+------+---------+------+ Das ist schon besser. Und hier ist der Trick: Für die Datensätze aus "note", für die es keinen Datensatz in der Tabelle "user" gibt ist die uid in der Tabelle "user" NULL. "select * from note left join user on note.uid=user.uid where user.uid is null;" +-----+------+---------+------+ | nid | uid | content | uid | +-----+------+---------+------+ | 6 | 5555 | NULL | NULL | +-----+------+---------+------+ Geht doch. Jetzt räumen wir noch schnell auf, damit alles wie vorher ist. drop database test; Stay cool, don't close the fridge. Autor: pbierans_(at)_lynet.de P. Bierans -- LYNET Kommunikation AG - http://www.lynet.de - Patrick Bierans Das Internet-Systemhaus fuer Multimedia- und Netzwerkloesungen Zentrale Luebeck Fon +49-451-6131-0, Fax +49-451-6131-333 Niederlassung Hamburg Fon +49-40-65738-0, Fax +49-40-65738-333 --- *** Weitere Infos zur Mailingliste und MySQL unter http://www.4t2.com/mysql
php::bar PHP Wiki - Listenarchive