SQL-Abfrage über 2 Tabellen
Scooter
- datenbank
Hi,
ich habe zwei Tabellen zu einem Online-Shop:
Kategorien und Produkte.
Jedes Produkt bekommt über einen Fremdschlüssel eine Kategorie zugeordnet.
Jedes Produkt hat eine Anzahl.
Nun möchte ich alle Kategorien anzeigen lassen, zu der es mindestens ein Produkt gibt, dessen Anzahl größer als Null ist. (es können Produkte gespeichert sein, die ausverkauft sind, also Anzahl = 0, dessen Kategorien sollen nicht angezeigt werden)
Wie mach ich das?
Habe folgendes versucht:
SELECT * FROM shop_categories, shop_products
WHERE shop_categories.categories_id = shop_products.categories_id
AND shop_products.anzahl > 0
Problem ist: wenn es mehrere Produkte gibt, die zur selben Kategorie gehören, dann wird diese Kategorie auch mehrmals aufgelistet. Natürlich soll sie nur genau einmal aufgelistet werden.
LIMIT 1 hilft da ja leider auch nicht, da dann immer nur eine Kategorie gelistet wird.
Habt ihr ne Idee??
Gruß
Scooter
Moin,
Problem ist: wenn es mehrere Produkte gibt, die zur selben Kategorie gehören, dann wird diese Kategorie auch mehrmals aufgelistet. Natürlich soll sie nur genau einmal aufgelistet werden.
Du suchst DISTINCT.
Hi,
Du suchst DISTINCT.
Hey, danke. Hast mir glaub ich schon geholfen. Allerdings weiß ich noch nicht so genau wie DISTINCT arbeitet:
Ich habe es nach dem SELECT geschrieben. Woanders darf es wohl nicht hin.
--> SELECT DISTINCT ...
wenn ich dann ein * nehme, klappts nicht. wenn ich nur die Spalten nehme, die ich brauche klappts!
Genauer gesagt habe ich heraus gefunden, wenn ich die Produkt ID noch mit hinzunehme, klappts nicht.
Wie arbeitet DISTINCT nun?? Ich finde darüber in der MySQL-Sprachreferenz nicht. Muss jeder Wert der ausgeählten Spalten unterschiedlich sein?? Oder wählt es bei Spalten in denen sich werte wiederholen nur einen aus? Welchen dann?
Wieso klappts nicht wenn ich alle Spalten auswähle??
Gruß
Scooter
Moin,
Wie arbeitet DISTINCT nun?? Ich finde darüber in der MySQL-Sprachreferenz nicht.
Naja, es hat nicht grade epische Breite, wird aber doch erwähnt:
| The options DISTINCT, DISTINCTROW and ALL specify whether duplicate
| rows should be returned. The default is (ALL), all matching rows are
| returned. DISTINCT and DISTINCTROW are synonyms and specify that
| duplicate rows in the result set should be removed.
-- MySQL-Referenzmanual, Abschnitt 6.4.1
Muss jeder Wert der ausgeählten Spalten unterschiedlich sein??
Jeder der Werte die du dir zurückgeben lässt darf nur einmal vorkommen. Hast du also eine Tabelle
Typ | Name
----+------------
Obst| Birne
Obst| Apfel
Pilz| Fliegenpils
und machst ein SELECT Typ FROM ... kriegst du Obst, Obst, Pilz. Machst du hingegegen SELECT DISTINCT Typ FROM ... kriegst du Obst, Pilz. SELECT DISTINCT * FROM ... würde dir hier nichts bringen, da ja alle Zeilen die er dir zurückgibt unterschiedlich sind.
Oder wählt es bei Spalten in denen sich werte wiederholen nur einen aus? Welchen dann?
Den ersten auf den es trifft. Wobei hier die Reihenfolge vermutlich nicht definiert ist. Für deine Betrachtungen solltest du also von "irgendeinen zufälligen" ausgehen.
Wieso klappts nicht wenn ich alle Spalten auswähle??
Ich nehme an dass du da noch IDs oder ähnliches hast die ohnehin immer unterschiedlich sind. So kann er die Spalten nicht als gleich erkennen.
Servus,
Du musst das ganze auf zwei Abfragen ausweiten.
Die erste liefert Dir eine Liste mit den Kathegorieren und die zweite arbeitet die Liste in aller ruhe ab und liefert zu jeder Kathegorie einen artikel.
Möglihckeiten gibt es dazu gerade ma genug.
Die erste wäre über einen join.
Das klappt jedoch nur in einer etwas höherwertigen Sprache wie PL/SQL T-SQL etc. leider nicht mit SQL selbst.
Sicher doch joinen kann man auch mit SQL aber nicht in dem Umfang wie wir es hier benötigen.
2. Möglihckeit die bessere öffnen eine Abfrge mit der Du eine Liste der Kathegorien holst z.B:
Sinngemäss!
result1 = sqlqery ("select katid from kathegorytable order by katname);
Jetzt musst Du erstes Script in eine while Schleife auswerten
while(result1)
result2 = sqlqery ("select prodid, prodname from prodtable where prodkatid = "+ result1 + " order ba prodname;
Ich hoffe Du kannst mit der eher Theoretischen und Syntaktisch völlig verhunzten Info was anfangen.
Gruss Matze
Hi,
while(result1)
result2 = sqlqery ("select prodid, prodname from prodtable where prodkatid = "+ result1 + " order ba prodname;
hm, dann hätte ich damit alle Produkte die einer kategorie zugeordnet sind.
weiß nicht ob mir das so hilft.
Das mit dem DISTINCT war schon ganz gut. Muss nur sehen, ob es auch wirklich für alle Fälle zutrifft.
Scooter
Dann must Du eben das zweite SQL etwas anpassen.
Das mit dem Distinct kannst Du gerne machen aber ohene obige Lösung kommst du nicht richtig dran, so wie Du es Beschrieben hast.
Gruss Matze
Moin,
Dann must Du eben das zweite SQL etwas anpassen.
Das mit dem Distinct kannst Du gerne machen aber ohene obige Lösung kommst du nicht richtig dran, so wie Du es Beschrieben hast.
Woran denn nun wieder? Der Ursprungsposter wollte eine Liste aller Kategorien in denen es ein Produkt gibt von dem noch mindestens ein Stück im Lager ist. Dazu holen wir uns eine Liste aller Produkte mit Anzahl > 0, joinen das mit der Kategorieliste und haben somit alle Produkte mit mindestens einem Stück im Lager und deren Kategorien. Die Produkte brauchen wir gar nicht sondern SELECTen nur die Kategorien. Das gibt schonmal die Liste wie wir sie haben wollen, bloß das eben noch Kategorien mehrfach auftauchen können. Genau daran dreht DISTINCT (bzw. GROUP BY Kategorie, aber eben unter Umständen weniger effizient).
Mir ist unklar wo du da die Notwendigkeit für zwei Abfragen sehen willst. (Zumal die Aufgabenstellung die du offenbar zu lösen glaubtest auch genau das Einsatzgebiet von JOINs ist. Möchtest du dich vielleicht noch ein bisschen mit SQL befassen bevor du wieder was dazu sagst?)
Servus,
lieber henryk
Mir ist unklar wo du da die Notwendigkeit für zwei Abfragen sehen >>willst. (Zumal die Aufgabenstellung die du offenbar zu lösen >>glaubtest auch genau das Einsatzgebiet von JOINs ist. Möchtest du >>dich vielleicht noch ein bisschen mit SQL befassen bevor du wieder >>was dazu sagst?)
tut mir sehr leid hab die Frage etwas falsch verstanden aber Deine "Arroganz" ist grad mal an der falchen Ecke gelandet.
Gruss Matze
Moin,
tut mir sehr leid hab die Frage etwas falsch verstanden aber Deine "Arroganz" ist grad mal an der falchen Ecke gelandet.
Dass du die Frage falsch verstanden hast war offensichtlich. Aber das mit dem nochmal anschauen hatte ich ernst gemeint. Vielleicht auch bloß weil ich nicht verstehe inwiefern dein
| result1 = sqlqery ("select katid from kathegorytable order by katname);
| while(result1)
| result2 = sqlqery ("select prodid, prodname from prodtable where prodkatid = "+ result1 + " order ba prodname;
etwas anderes liefert, oder in irgendeiner Form besser ist, als
SELECT katid, prodid, prodname FROM kathegorytable, prodtable WHERE prodkatid = katid ORDER BY katname, prodname
vor allem da du im selben Post vorher behauptest hast "joinen kann man auch mit SQL aber nicht in dem Umfang wie wir es hier benötigen".
Servus,
wie schon gesagt ich habe die Fragestellung falsch verstanden.
Somit ist auch der "join" den ich für,angemessen gehalten hätte über SQL nicht mehr möglich.
Gruss matze
PS Ich weiss eure grösste Freude ist es doch teilweise in dem Forum jemanden der falsch liegt als Narren hinzustellen.
Hi Henryk,
Problem ist: wenn es mehrere Produkte gibt, die zur selben Kategorie gehören, dann wird diese Kategorie auch mehrmals aufgelistet. Natürlich soll sie nur genau einmal aufgelistet werden.
Du suchst DISTINCT.
was hältst Du von "GROUP BY"?
Viele Grüße
Michael
Moin,
was hältst Du von "GROUP BY"?
Weniger. MySQL wandelt DISTINCT zwar intern in GROUP BY um, kann bei DISTINCT aber unter Umständen früher aufhören die Tabellen zu durchsuchen. Siehe MySQL-Referenz, Abschnitt 5.2.5.