SQL Group by nicht verstanden
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
abfrage
aggregat
angabe
artikel
code
datensatz
feld
globale netze
gruppe
gruppierten felder
klausel
lieferer
machen
sinn
spalte
standard
statement
stattfinden
url
zusammenfassung
-
Hallo Vl könnt ihr mir helfen ein SQL Statement zu verstehen:
Ich habe da 3 Tabellen
Lieferer
Artikel
Prüfer
Sieh Unten
Davon möchte ich jetzt in einem SQL Statement alle Lieferer (von diesen IdNr & Namen) haben,
die Artikel von allen Prüfern haben
Die Abfrage funktioniert:
SELECT Lieferer.idnr, Lieferer.name FROM Lieferer, Artikel WHERE Lieferer.idnr = Artikel.idnr GROUP BY Lieferer.name, Lieferer.idnr HAVING Count(Lieferer.idnr)=4
(die 4 kann mana uch durch ein Subselect machen, aber das ist hier nicht das wichtige)
Allerdings verstehe ich nicht, wieso ich in dem GROUP BY beide brauche … wenn ich eines weglasse stimmt es nicht mehr.
Tabellen:
Lieferer
IDNR KENNZAHL NAME 1234567 810 Maier 1234568 754 Bauer 2345617 754 Müllner 1234569 710 Lehner 3456712 810 Hofer 1234561 752 Schmied 1234560 752 Bäcker 4567891 754 Fischer 5678901 710 Lech
Artikel
PRUEFNUMMER IDNR NAME 01 1234567 WET 01 2345617 WET1 01 3456712 WET2 02 2345617 Substitubsi 02 1234561 Globale Netze 02 5678901 Globale Netze 02 4567891 Substitubsi 03 4567891 Waltzwerk 03 5678901 Waltzwerk 03 1234561 Artikel kalr1 03 2345617 Netzwerke 04 2345617 Artikel klar2 04 1234561 Kabelsammlung 04 4567891 Kabelsammlung 04 3456712 Transformator
Pruefer
PRUEFNUMMER NAME 01 Maisner 02 Stiegl 03 Waller 04 Diedl
Ergebniss
IdNr Name 2345617 Müllner
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hallo mprev,
in Standard-SQL wäre es folgendermaßen:
Sobald eines der im SELECT-Statement ausgewählten Felder ein Aggregat, d.h. ein berechnetes Feld (MIN(), MAX(), COUNT(), AVG(), SUM(), ...), ist müssen alle Felder, die kein Aggregat sind, in der GROUP-BY-Klausel aufgelistet werden. Wenn keine Aggregate ausgewählt sind aber eine GROUP-BY-Klausel existiert, dann müssen dort alle gewählten Felder aufgelistet sein.
Normalerweise ist es nicht zulässig ein oder mehrere Nicht-Aggregat-Felder auszulassen, da das keinen Sinn macht.
Wäre es zulässig ein Feld auszulassen, dann können in einem solchen Fall alle Aggregatfunktionen nur auf einen Datensatz angewendet werden, da bezüglich der nicht gruppierten Felder keine Zusammenfassung stattfinden kann, auch wenn sie den selben Wert enthalten.
Ich entnehme Deinem Posting jetzt mal, dass sowas unter MySQL zulässig ist.
Dann führt das dazu, dass Du anstelle von einem Datensatz mit Count(Lieferer.idnr)=4 vier Datensätze mit jeweils Count(Lieferer.idnr)=1 bekommst, was dann natürlich der HAVING-Klausel widerspricht. -
Ich merke mir ist hier noch einiges mit GROUP BY unklar.
darkpandemic schrieb:
in Standard-SQL wäre es folgendermaßen:
Sobald eines der im SELECT-Statement ausgewählten Felder ein Aggregat, d.h. ein berechnetes Feld (MIN(), MAX(), COUNT(), AVG(), SUM(), ...), ist müssen alle Felder, die kein Aggregat sind, in der GROUP-BY-Klausel aufgelistet werden. Wenn keine Aggregate ausgewählt sind aber eine GROUP-BY-Klausel existiert, dann müssen dort alle gewählten Felder aufgelistet sein.
Das verstehe ich nicht. Ich dachte (oder stellte es mir so vor) das bei einem GROUP-BY
und der Angabe einer Spalte(column) die Elemente gruppiert werden.
So dass jene Zeilen(row) die eine Gleichen Wert haben zusammen in einer Gruppe sind.
darkpandemic schrieb:
Normalerweise ist es nicht zulässig ein oder mehrere Nicht-Aggregat-Felder auszulassen, da das keinen Sinn macht.
Wäre es zulässig ein Feld auszulassen, dann können in einem solchen Fall alle Aggregatfunktionen nur auf einen Datensatz angewendet werden, da bezüglich der nicht gruppierten Felder keine Zusammenfassung stattfinden kann, auch wenn sie den selben Wert enthalten.
Aber wieso sind die dann nicht gruppiert, das verstehe ich wohl nicht?
Oder werden nicht die gesamten Zeilen (row) sondern jeweils nur die Werte einer Spalte gruppiert?
darkpandemic schrieb:
Ich entnehme Deinem Posting jetzt mal, dass sowas unter MySQL zulässig ist.
Dann führt das dazu, dass Du anstelle von einem Datensatz mit Count(Lieferer.idnr)=4 vier Datensätze mit jeweils Count(Lieferer.idnr)=1 bekommst, was dann natürlich der HAVING-Klausel widerspricht.
Ob es auf MySQL zulässig ist wüste ich nicht. Obiges Beispiel läuft auf Oracle (Version k.a.).
Aber wenn ich 4 mit 1 erhalte müsste das Result leer sein, nicht Falsch oder?
Aber cih dachte ben, dass mit einem einfachn Grouping das schon die Zusammengehörenden zusammen gegrouped sind. Und der Count dann in diesen ausgewertet wird.
-
Hallo mprev,
mprev schrieb:
ich habe gerade mit SQLite rumgespielt und da ist es tatsächlich so, wie Du es sagst. Allerdings hatte ich auch schon Datenbanken bei denen es anders war. Es scheint so zu sein, dass das überall etwas anders gehandhabt wird. Hier habe ich die Doku zum Oracle GROUP BY. Dort steht allerdings, dass es so ist, wie ich es oben beschriebe habe. Insbesondere:
... Ich dachte (oder stellte es mir so vor) das bei einem GROUP-BY
und der Angabe einer Spalte(column) die Elemente gruppiert werden.
So dass jene Zeilen(row) die eine Gleichen Wert haben zusammen in einer Gruppe sind.
...
All the columns used besides the aggregate functions must be included in the GROUP BY clause.
D.h. wenn die GROUP-BY-Auflistung unvollständig ist, dann hätte die Abfrage eigentlich gar nicht ausgeführt werden dürfen sondern stattdessen ein Fehler auftreten müssen.
Das sich das bei Dir anders verhält wundert mich jetzt ein bisschen. Aber Du kannst ja mal in der mitgelieferten Doku nachschauen, was dort zum Thema steht.
Eine Sache ist mir noch aufgefallen. Im ersten Posting schreibst Du:
mprev schrieb:
Deine Abfrage wählt aber alle Lieferer aus, denen genau vier Artikel zugeordnet sind.
...
Davon möchte ich jetzt in einem SQL Statement alle Lieferer (von diesen IdNr & Namen) haben,
die Artikel von allen Prüfern haben
...,
Wenn Du alle Lieferer haben willst, die mit allen Prüfern zu tun haben, dann musst Du das wie folgt machen:
Damit wird auf die Anzahl der zugeordneten Prüfer anstatt der Anzahl der Artikel geprüft.SELECT lieferer.name, lieferer.idnr FROM lieferer INNER JOIN (SELECT DISTINCT artikel.idnr , artikel.pruefnummer FROM artikel) AS subq ON lieferer.idnr = subq.idnr GROUP BY lieferer.name, lieferer.idnr HAVING COUNT(lieferer.idnr) = (SELECT COUNT(pruefer.name) FROM pruefer);
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage