• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Verschachtelte MySql Abfrage

Mark

Neues Mitglied
Ich brauche eine doppelte Abfrage, sortiert nach einem Feld in der Zweiten.
Das geht vermutlich mit inner select, aber mit der Syntax dazu stehe ich noch auf Kriegsfuss.

Die umständliche Variante wäre etwa so:

Code:
$abfrage = mysql_query("SELECT * FROM `tabelle1`");
while($row = mysql_fetch_object($abfrage))
{
$name = mysql_fetch_object(mysql_query("SELECT `name` FROM `tabelle2` WHERE `userid` = ".$row->userid));
$row->name = $name->name;
$liste[] = $row;
}
// $liste nach name sortieren

Ist jemand so nett und gibt mir die Syntax für die Abfrage mit inner select?
 
Genau mit der Seite stehe ich auf Kriegsfuss.
Entweder reicht mein englisch nicht, oder ich bin zu blöd das zu verstehen.

Anders gesagt, ich habe nie viel mit MySql gemacht, und wenn, dann habe ich mir immer so umständliche Lösungen zusammen gebastelt, weil ich mit usort() in PHP einfach besser klar komme als mit inner join und inner select.
Dass das Ganze viel praktischer und vor allem schneller ist, wenn man denn die richtigen queries kennt, ist mir erst vor kurzem aufgegangen, sprich da steht mein Wissen noch ganz am Anfang und dieses MySql-Manual ist für mich fast alles chinesisch.
 
Oha, ich habe das immer andersrum versucht, vielleicht war das mein Fehler?
So wie ich mich kenne breche ich mir mit dem order by nochmal einen ab und wieso der in dem Fall nur die Datensätze aus tabelle2 nimmt, die in tabelle1 vorkommen ist mir auch noch nicht klar.
Aber auf jeden Fall danke für die Antwort.
 
left join macht nix anderes als die Abfrage sozusagen zwei zu teilen, in linke seite und rechte seite. die linke seite wird zurückgegeben/ausgegeben, unter der bedingung der rechte seite.

mal so grob umschrieben
right join gewissermasßen anders herum ;)
 
Cool, danke, das ist mal eine Erklärung die ich verstehe.
Ich glaube fast, damit bringe ich den Rest jetzt selber auf die Reihe.
 
Das ist alles aus dem Kopf und ungetestet. (Mache ich nachher noch und editiere, wenn ich mich verhauen haben sollte.)

Code:
SELECT
        b.`name`
FROM
        `tabelle1` AS a
LEFT JOIN
        `tabelle2` AS b
    ON
        a.`userid` = b.`userid`

LEFT JOIN gibt eine Ergebnismenge zurück, die jede Zeile aus der Ausgangstabelle enthält (egal, ob die ON-Bedingung für manche Zeilen der Ausgangstabelle nicht zutrifft).

RIGHT JOIN gibt eine Ergebnismenge zurück, die jede Zeile aus der hinzugefügten Tabelle enthält. Das lässt sich dann oft zu einem LEFT JOIN umdrehen, indem die Tabellen vertauscht werden.

INNER JOIN gibt nur die Zeilen zurück, bei denen die ON-Bedingung zutrifft.

Das klingt kompliziert, ist aber eigentlich recht einfach.

Code:
Tabelle user:

 id | name
----+------
  1 | Bob
  2 | Tom
  3 | Mia

Tabelle post:

 id | user_id | content
----+---------+---------
  1 |       2 | ...
  2 |       2 | ...
  3 |    null | ...

Code:
---------------------------------------
(1) LEFT JOIN
---------------------------------------
  
SELECT
        u.`id`,
        u.`name`,
        p.`id`,
        p.`content`
FROM
        `post` AS p
LEFT JOIN
        `user` AS u
    ON
        p.`user_id` = u.`id`
        
 u.id | u.name | p.id | p.content
------+--------+------+-----------
    2 |    Tom |    1 | ...
    2 |    Tom |    2 | ...
 null |   null |    3 | ...    

Die Ergebnismenge enthält jeden Post.

Code:
---------------------------------------
(2) RIGHT JOIN
--------------------------------------- 
 
SELECT
        u.`id`,
        u.`name`,
        p.`id`,
        p.`content`
FROM
        `post` AS p
RIGHT JOIN
        `user` AS u
    ON
        p.`user_id` = u.`id`
        
 u.id | u.name | p.id | p.content
------+--------+------+-----------
    1 |    Bob | null | null
    2 |    Tom |    1 | ...
    2 |    Tom |    2 | ...
    3 |    Mia | null | null            
    
Die Ergebnismenge enthält jeden User.

Code:
---------------------------------------
(3) INNER JOIN
--------------------------------------- 
 
SELECT
        u.`id`,
        u.`name`,
        p.`id`,
        p.`content`
FROM
        `post` AS p
INNER JOIN
        `user` AS u
    ON
        p.`user_id` = u.`id`
        
 u.id | u.name | p.id | p.content
------+--------+------+-----------
    2 |    Tom |    1 | ...
    2 |    Tom |    2 | ...
    
Die Ergebnismenge enthält nur Einträge, für die die ON-Bedingung sauber
erfüllt ist.

Da etwas wie die null bei der user_id von Post #3 in einem intakten Schema in vielen Fällen nicht auftaucht, ist der LEFT JOIN häufig identisch zum INNER JOIN.
 
Zuletzt bearbeitet:
Was wäre mit diesem Konstrukt?

Code:
SELECT
    t2.name
FROM
    tabelle2 AS t2,
    tabelle1 AS t1
WHERE
    t1.userid = t2.userid

Findet sich auch so in der Doku wieder:

MySQL :: MySQL 5.1 Referenzhandbuch :: 13.2.7 SELECT
MySQL :: MySQL 5.1 Referenzhandbuch :: 13.2.7.1 JOIN

Scheint mir irgendwie eine Art Alternativ-Syntax für einen JOIN zu sein. Es wäre schön wenn jemand dazu was sagen könnte, denn mich würde das mal interessieren ob das intern wie ein JOIN gehandhabt wird und/oder ob es Performance-Unterschiede zwischen dieser und der üblichen Schreibweise gibt.
 
UUUUFFFFF, das klingt wirklich kompliziert.
Aber in den Beispielen sieht es dann halbwegs einfach aus.
Vielen Dank für die Mühe.

Ich brauche also right join, weil ich aus tabelle2 nur die Namen der User suche, deren Datensätze ich in tabelle1 habe, wobei ich alle Datensätze aus tabelle1 brauche aber in tabelle2 noch mehr Namen stehen.

Wenn ich das dann noch nach Namen sortieren will, wäre das etwa so

Code:
SELECT
        a.`name`
FROM
        `tabelle2` AS a
RIGHT JOIN
        `tabelle1` AS b
    ON
        a.`userid` = b.`userid`
ORDER BY
        a.`name`

Der Vollständigkeit halber, weil ich gerade einen Anflug von Verständnis habe,
wenn ich auch in tabelle1 nur bestimmte Datensätze lesen will, wohin mit where und/oder limit?

Ich rate einfach mal

Code:
SELECT
        a.`name`
FROM
        `tabelle2` AS a
RIGHT JOIN
        `tabelle1` AS b
    ON
        a.`userid` = b.`userid`
WHERE b.`xy` > 10
ORDER BY
        b.`name`
LIMIT 0,10

Vermutlich falsch?
 
newlord schrieb:
Scheint mir irgendwie eine Art Alternativ-Syntax für einen JOIN zu sein. Es wäre schön wenn jemand dazu was sagen könnte, denn mich würde das mal interessieren ob das intern wie ein JOIN gehandhabt wird und/oder ob es Performance-Unterschiede zwischen dieser und der üblichen Schreibweise gibt.

Das nennt sich im allgemeinen Sprachgebrauch – inhaltlich nicht ganz exakt – „theta-style join“. Meiner Wahrnehmung nach ist diese Schreibweise bei der Mehrheit der Programmierer unbeliebt und gilt als veraltet.

Praktisch kannst du wohl – hoffentlich – davon ausgehen, dass die Syntax intern wie ein Join in anderer Schreibweise ausgewertet wird. In MySQL also wie JOIN, was meines Wissens äquivalent zu INNER JOIN ist. (Es ist für mich irgendwie schwierig, so was in Dokus zu finden.)

Das hängt aber alles gerne vom konkreten DBMS ab. Ich würde klar die andere Syntax empfehlen.

Mark schrieb:
Ich brauche also right join, weil ich aus tabelle2 nur die Namen der User suche, deren Datensätze ich in tabelle1 habe, wobei ich alle Datensätze aus tabelle1 brauche aber in tabelle2 noch mehr Namen stehen.

Ja, wenn meine Ausführungen stimmen, stimmt das auch. Wobei ich zumeist „von links“ joine, weil ich mehr von „links nach rechts“ denke.

Code:
SELECT
        b.`name`
FROM
        `tabelle1` AS a
LEFT JOIN
        `tabelle2` AS b
    ON
        a.`userid` = b.`userid`
ORDER BY
        b.`name`

„Zu jedem Eintrag aus tabelle1 will ich etwas aus tabelle2.“

Ich rate einfach mal

Gut geraten.

Von der Vorstellung her werden WHERE, ORDER BY und LIMIT auf die „zusammengejointe“ Ergebnismenge angewendet.



Edit: Habe es jetzt getestet. Die Beispiele aus #8 passen alle.
 
Zuletzt bearbeitet:
Zusatzfrage:

Ich habe gerade bemerkt, dass es scheinbar keinen Unterschied macht, ob man beim WHERE oder ORDER BY noch a. oder b. dazu schreibt.

Code:
SELECT
        b.`name`
FROM
        `tabelle1` AS a
LEFT JOIN
        `tabelle2` AS b
    ON
        a.`userid` = b.`userid`
ORDER BY
        b.`name`

ist identisch zu

Code:
SELECT
        b.`name`
FROM
        `tabelle1` AS a
LEFT JOIN
        `tabelle2` AS b
    ON
        a.`userid` = b.`userid`
ORDER BY
        `name`

Ist das so richtig?
 
Wenn in beiden Tabellen nur ein Feld mit dem Namen name enthalten ist, dürfte die Zuordnung dort auch ohne Tabellenalias eindeutig möglich sein.

Ich finde es aber übersichtlicher, das Alias zu setzen.
 
Zurück
Oben