Weiter Zurück [Inhalt] Online Suche im Handbuch

31.15 Zählen in Spalten

In der Praxis stellen sich oft immer wieder dieselben fragen. Grund können statistische Erhebungen sein. Auf unsere tier Datenbank bezogen, könnte man die Fragen stellen:

Wie oft kommt ein bestimmter Typ von Einträgen in einer Tabelle vor ? Wir fragen z.B. nach der Zahl der Tiere, der Zahl von Tieren je Besitzer, oder der Zahl der noch lebenden Tiere.....

Um diese Fragen alle beantworten zu können, müssen wir einige wichtige Informationen zu vor wissen. Z.B. wieviele Spalten es überhaupt in unserer Tabelle gibt. Hierfür benutzen wir den Operator COUNT():


mysql> SELECT COUNT(*) FROM tier;
+----------+
| COUNT(*) |
+----------+
|        9 |
+----------+
Ok, soweit so gut, der Operator COUNT(*) zählt also alle Spalten. Wir möchten aber z.B. wissen, wieviele Tiere ein Besitzer hat:


mysql> SELECT besitzer, COUNT(*) FROM tier GROUP BY besitzer;
+-----------+----------+
| besitzer  | COUNT(*) |
+-----------+----------+
| Benny     |        2 |
| Diane     |        2 |
| Gwen      |        3 |
| Harold    |        2 |
+-----------+----------+

Was zählen wir hier eigendlich ? Übersetzen wir das Statement einmal auf Deutsch:

Selektiere nach allen Besitzern, zähle alles aus der datenbank tier und gruppiere nach besitzer.

Nun auch keine große Hilfe !(mir ging es ebenso)

Erinnern wir uns an die frührern SELECT Befehle:


mysql> SELECT name, geboren FROM tier ORDER BY geboren DESC;

Stellen wir nun die neuen Befehle gegenüber:


mysql> SELECT besitzer, COUNT(*) FROM tier GROUP BY besitzer;

Der Hauptunterschied liegt darin, daß wir eine neue Ausgabespalte einführen (COUNT(*)), in der dann doppelte Zeilen gezählt und ausgegeben werden.

Man sollte hier niemals das GROUP BY Statement vergessen, ansonsten gibt es eine Fehlermeldung:


mysql> SELECT besitzer, COUNT(besitzer) FROM tier;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause

Um diese Fehlermeldung verstehen zu können, bedarf es etwas Einfühlungsvermögen in MySQL und den SQL Parser. Die Erfahrung bekommt man durch viel Übung. Hilfreich sind bei SQL-Datenbanken stets ausgiebige Fehlermeldungen, welche auch Aussagefähig sind. Obige Fehlermeldung stiftet mehr Verwirrung als sie hilfreich ist, dadurch, daß sie unbekannte Ausdrücke ausgibt. Um durchzublicken, muß man wissen, wie ein SQL Parser vorgeht: Zuerst wird der Befehl SELECT interpretiert. Hier erfährt der Parser, daß die Spalten besitzer und noch eine weitere Spalte auszugeben ist, wobei alle Elemente dieser Spalte gezählt werden sollen (COUNT(*)). In der Klammer steht * für alle. Der Befehl COUNT() könnte auch noch andere Auswahlkriterien enthalten, außer (*). Woher soll nun der Parser wissen, welches die zweite Spalte ist, die zu sortieren ist ? FROM tier ist obligatorisch und gibt die Datenbank an. Es fehlt also ein Operator, der dem COUNT Befehl sagt, welche Spalte er zählen soll. Hierfür wurde dann der Operator GROUP BY eingeführt. COUNT() und GROUP BY gehören also immer zusammen. Der obige Fehler war, daß COUNT() in der Klammer ein Auswahlkriterium oder eine Bedingung erwartet, jedenfalls keinen Namen der Spalte. MySQL beanstandet, daß kein GROUP BY Ausdruck vorhanden ist. GROUP columns sind die Befehle (COUNT() oder auch MIN() oder MAX()). Zu NON GROUP columns zählt besitzer.

MySQL meint also, daß erstens der Ausdruck GROUP BY fehlt und hier nicht besitzer mit COUNT zusammengehört.

MySQL ist für die Qualität der Fehlermeldungen nicht gerade berühmt, andere SQL Datenbanken sind aber auch nicht viel besser.

COUNT() und GROUP BY sind nützlich, um Daten zu charakterisieren, also zu gruppieren und zu zählen. Die folgenden Beispiele zeigen, wie man aus einer Datenbank aussagefähige Statistiken gewinnt. Wir zählen einmal die Tiere je Spezies:

mysql> SELECT spezies, COUNT(*) FROM tier GROUP BY spezies;
+---------+----------+
| spezies | COUNT(*) |
+---------+----------+
| bird    |        2 |
| cat     |        2 |
| dog     |        3 |
| hamster |        1 |
| snake   |        1 |
+---------+----------+

Die Zahl der Tiere, nach Geschlecht geordnet:

mysql> SELECT geschlecht, COUNT(*) FROM tier GROUP BY geschlecht;
+-------------+----------+
| geschlecht  | COUNT(*) |
+-------------+----------+
| NULL        |        1 |
| w           |        4 |
| m           |        4 |
+-------------+----------+

In einem Falle war das Geschlecht nicht zu bestimmen....Nun zählen wir Tiere und sortieren nach Spezies und Geschlecht:

mysql> SELECT spezies, geschlecht, COUNT(*) FROM tier GROUP BY spezies, geschlecht;
+---------+-------------+----------+
| spezies | geschlecht  | COUNT(*) |
+---------+-------------+----------+
| bird    | NULL        |        1 |
| bird    | w           |        1 |
| cat     | w           |        1 |
| cat     | m           |        1 |
| dog     | w           |        1 |
| dog     | m           |        2 |
| hamster | w           |        1 |
| snake   | m           |        1 |
+---------+-------------+----------+

Was ist hier passiert ? Ganz einfach: Wir geben die Spalten Spezies, geschlecht aus und in der dritten Spalte zählen wir die doppelten Einträge der beiden Spalten.

Wenn wir nur Katzen und Hunde zählen wollen, brauchen wir natürlich die anderen Tiere nicht mit ausgeben lassen:

mysql> SELECT spezies, geschlecht, COUNT(*) FROM tier
    -> WHERE spezies = "dog" OR spezies = "cat"
    -> GROUP BY spezies, geschlecht;
+---------+-------------+----------+
| spezies | geschlecht  | COUNT(*) |
+---------+-------------+----------+
| cat     | w           |        1 |
| cat     | m           |        1 |
| dog     | w           |        1 |
| dog     | m           |        2 |
+---------+-------------+----------+

Ein langes Statement. Es hält sich aber an das, was wir bereits kennen. COUNT() und GROUP BY stehen da, wenn auch durch den WHERE Operator voneinander getrennt. Man sollte sich stets die Reihenfolge SELECT ... FROM ... WHERE genau merken. COUNT muß nach dem SELECT stehen und GROUP BY steht immer am Ende.

mysql> SELECT spezies, geschlecht, COUNT(*) FROM tier
    -> WHERE geschlecht IS NOT NULL
    -> GROUP BY spezies, geschlecht;
+---------+-------------+----------+
| spezies | geschlecht  | COUNT(*) |
+---------+-------------+----------+
| bird    | w           |        1 |
| cat     | w           |        1 |
| cat     | m           |        1 |
| dog     | w           |        1 |
| dog     | m           |        2 |
| hamster | w           |        1 |
| snake   | m           |        1 |
+---------+-------------+----------+

So, mit diesen Abfragemöglichkeiten kann man schon eine ganze Menge machen. Befriedigend ist unsere Tabelle jedoch nicht. Wir möchten weitere Informationen speichern und eventuell diese miteinander verknüpfen.


Weiter Zurück [Inhalt] Online Suche im Handbuch