SQL: Abfrage über mehrere Tabellen ohne Primärschlüssel=Fremdschlüssel
Hallo zusammen, ich erarbeite mir gerade MySQL und habe mir folgende Tabellen erstellt in MySQL (siehe Bilder). Nun möchte ich folgende Aufgabe lösen: Gib alle Produkte an, bei der die Menge mehr als 1000 ist. Gib die größte Menge zuerst an. Dies habe ich mit folgender Syntax gemacht: SELECT Produktname,Menge FROM verkaufsberichte,produkte WHERE Menge>1000 order by Menge desc;
Als Ausgabe erhalte ich natürlich Mist (siehe weiteres Bild), weil ich noch nicht Primärschlüssel=Fremdschlüssel eingegeben habe. Aber was gibt mir mySQL hier eigentlich aus? Dankeschön!
4 Antworten
Man kann Tabellen genz normal mit where-Bedingungen ohne join-Syntax verknüpfen. Auch ist dazu weder Primär- noch Fremdschlüssel erforderlich. Die Daten müssen das von der Logik natürlich hergeben, das ist klar. Es können auch Datengruppen verwendet werden, um die Sätze eindeutig zu identifizieren. Der Fremdschlüssel dient eigentlich nur dazu, seitens der Datenbank unerwünschte Eintragungen zu verhindern.
Beispiel:
select * from tabelle-1, tabelle-2
where tabelle-1.mitgliedsnr = tabelle-2.mitgliedsnr
and tabelle-1.datum = tabelle-2.datum
Hier werden zwei Tabellen miteinander verknüpft, deren Sätze mit der mitgliedsnr und dem datum gleichzeitig übereinstimmen (die Namen der Felder müssen nicht übereinstimmen, hier nur wegen der Übersichtlichkeit) . Ein Index sollte auf den Feldern schon vorhanden sein, zumindest bei größeren Datenmengen.
Ich betreibe seit 20 Jahren eine Datenbank für einen Rassehundeverein mit mittlerweile 55 Tabellen. Da sind auch Datenkonstruktionen dabei, die sich nicht mit dem klassischen Datenbankdesign lösen lassen, wie es in der Schule gelehrt wird. Bei einer Ahnentafel z.B. sind Eltern und Großeltern in der selben Tabelle gespeichert und müssen verknüpft werden. Eine SQL-Datenbank bietet weit mehr Anwendungsmöglichkeiten, als in der Schule gelehrt wird.
Ich mache übrigens alle Verknüpfungen auf diese Weise Das ist für mich übersichtlicher. Der Zugriff auf die Datenbank erfolgt meistens vom Programm aus über Embedded-SQL. Da gibt es oft einfachere Möglichkeiten zur Lösung von komplexen Zusammenhängen.
Hello there,
also was du da ausgegeben hast, nennt man kartesisches Produkt und was du durchgeführt hast, war wie richtig bemerkt wurde, ein CROSS JOIN. Aber aufgepasst! Unter MySQL gibt es den Befehl CROSS JOIN zwar, er führt aber keinen klassischen CROSS JOIN durch sondern bereinigt bereits, ähnlich einem INNER JOIN.
In der Regel wird dieses kartesische Produkt nicht gewünscht und muss daher bereinigt werden. Wie auch richtig erwähnt wurde, ist das Schlüsselwort JOIN nicht zwingend erforderlich.
Es gibt nämlich zwei gültige Syntax für die Formulierung eines Joins.
Das eine wäre explizit, weil du das Schlüsselwort JOIN "explizit" erwähnst.
Also so:
SELECT produktname,
menge
FROM verkaufsberichte
CROSS JOIN produkte
WHERE menge > 1000
ORDER BY menge DESC;
Unter MySQL ist dies äquivalent zu
SELECT produktname,
menge
FROM verkaufsberichte
INNER JOIN produkte
WHERE menge > 1000
ORDER BY menge DESC;
Was du machst ist der implizite JOIN:
SELECT produktname,
menge
FROM verkaufsberichte,
produkte
WHERE menge > 1000
ORDER BY menge DESC;
und den müsstest du natürlich noch bereinigen jetzt, genau - damit dein kartesisches Produkt weg ist:
SELECT produktname,
menge
FROM verkaufsberichte,
produkte
WHERE menge > 1000
AND verkaufsberichte.produkte_produktnummer = produkte.produktnummer
ORDER BY menge DESC;
Grundsätzlich ist der implizite JOIN ausreichend wenn du immer INNER JOINS machen musst, wenn du aber OUTER JOINS brauchst, dann wirds mit der impliziten Variante etwas unübersichtlich. Ich persönlich schreibe eigentlich nur explizite JOINS.
Hoffe nun bist du geholfen :) Vielleicht isses dir ja nen Stern wert
MfG
Alex
Was du da bekommst dürfte ein Cross-Join sein. Jede Zeile von Tabelle1 wird mit jeder Zeile von Tabelle2 Kombiniert.
SELECT p.Produktname, v.Menge FROM Produkte p LEFT JOIN Verkaufsberichte v ON (p.Produktnummer = v.Produkte_Produktnummer) WHERE v.Menge > 1000 ORDER BY v.Menge DESC;
Cross join inner join cross joint inner joint