(MySQL) Bekomme die Reihen nicht wie gewünscht gezählt
Knud Schröder
- datenbank
Hallo,
In einer Tabelle buchen eine ganze Reihe von Mitarbeitern Tag für Tag,
Monat für Monat.Das heisst, es gibt in einem gewissen Zeitraum viele Mitarbeiter, die viele Buchungen getätigt haben.
Jetzt interessiert mich, wieviele Mitarbeiter denn nun im Endeffekt schon buchen, unabhängig wieviele.
Mit
select personalnummer,count(*) from buchungen group by personalnummer;
werden mir die Anzahl der Buchungen je Personalnummer gezeigt.
Mit
select count(*) from buchungen;
Alle Buchhungen überhaupt.
Ich hab aber leider keine Ahnung, wie ich personalnummern denn schließlich gebucht haben. Aber vielleicht jemand von Euch?
Gruß,
Knud
Hi Knud
In einer Tabelle buchen eine ganze Reihe von Mitarbeitern Tag für Tag,
Monat für Monat.Das heisst, es gibt in einem gewissen Zeitraum viele Mitarbeiter, die viele Buchungen getätigt haben.
Jetzt interessiert mich, wieviele Mitarbeiter denn nun im Endeffekt schon buchen, unabhängig wieviele.
Sehe ich das richtig, du willst die Anzahl der Mitarbeiter welche
in einem bestimmten Zeitraum gebucht haben?
select count(mitarbeiter.mitarbeiter)
from mitarbeiter
inner join buchungen
on (mitarbeiter.mitarbeiter = buchungen.mitarbeiter)
where buchungen.datum between datum1 and datum2
Ich gehe jetzt einfach mal davon aus, du hast auch eine
eigene Tabelle für die Mitarbeiter, dann zählst du
alle Mitarbeiter, welche mindestens ein Eintragung
in der Buchungstabelle im betreffenden Zeitraum haben.
Gruss Daniela
Hi
select count(mitarbeiter.mitarbeiter)
from mitarbeiter
inner join buchungen
on (mitarbeiter.mitarbeiter = buchungen.mitarbeiter)
where buchungen.datum between datum1 and datum2
Leider zählt er trotzalledem dann _alle_ Buchungen in diesem Zeitraum.
Geht nicht vielleicht so ne Art count(count(*))?
Gruß,
Knud
Hi
Leider zählt er trotzalledem dann _alle_ Buchungen in diesem Zeitraum.
Upsi, du hast völlig recht, das passiert mir dauernd *schäm*
Geht nicht vielleicht so ne Art count(count(*))?
Ich wüsste nicht wie, in normalem SQL würde ichs lösen mit
select count(personen)
from personen
where exists (select *
from buchungen
where datum between datum1 and datum2)
Dass ist aber ein SubSelect welcher MySQL leider nicht beherrscht.
Im Moment fällt mir keinerlei Möglichkeit ein das ganze Problem
ohne Subselect ohne n Script zu lösen. Spukt mir aber die
ganze Zeit im Kopf rum das Problem.
Gruss Daniela
Hi Daniela,
Im Moment fällt mir keinerlei Möglichkeit ein das ganze Problem
ohne Subselect ohne n Script zu lösen.
ist das nicht der klassische Anwendungsfall von temporären Tabellen
in mySQL?
Viele Grüße
Michael
Hi Michael
ist das nicht der klassische Anwendungsfall von temporären Tabellen
in mySQL?
Ich hab mal Ludwigs Lösung mit dem distinct innerhalb des counts
ausprobiert, sie scheint zu funktionieren, also nicht nötig.
Viele setzen sich so für die Durchsetzung des HTML-Standards ein,
einen Standard für SQL gibts schon viel länger, und die Umsetzung
davon ist noch viel fürchterlicher mit proprietären Erweiterungen
und einfachsten Sachen die nicht unterstützt werden. Im Moment
kann MySQL zb ja noch nicht einmal SQL-92 :(. Der Distinct
innerhalb von count sieht mir auch nicht wirklich sauber ein.
Ich wäre für ein Banner, fully SQL-92/SQL-99... compliant...
Gruss Daniela
P.S. hab ich schonmal erwähnt das mir MySQL gehörig auf den
Keks geht, vorallem im Vergleich zu DB/2?
Hi Daniela,
Ich wäre für ein Banner, fully SQL-92/SQL-99... compliant...
das Problem dabei ist, daß ein solches Banner ja niemanden interessiert
außer der Handvoll Implementierer hinter den Kulissen.
P.S. hab ich schonmal erwähnt das mir MySQL gehörig auf den
Keks geht, vorallem im Vergleich zu DB/2?
Was die Implementierung einer _richtigen_ Datenbank angeht, so habe ich
davor einen Heidenrespekt. Die Komplexität beispielsweise eines Webservers
ist im Vergleich dazu m. E. völlig harmlos - der muß es ja 'nur' richtig
machen.
Insofern finde ich, daß sich mySQL schon recht tapfer schlägt.
Ich erwarte gar nicht, daß es mit DB2 oder Oracle konkurrieren kann.
Viele Grüße
Michael
Hi,
select personalnummer,count(*) from buchungen group by personalnummer;
Da ich grad keine DB zur hand habe um es auszuprobiern rat ich mal ins blaue:
select DISTINCT personalnummer from buchungen;
sollte jede personalnummer nur einmal ausgeben.
select DISTINCT count(personalnummer) from buchungen;
Sollte die summer von den personalnummern ausgeben, wobei jeder personalnummer nur einmal gezählt wird.
wie gesagt UNTESTED, ich weiß nicht wie DISTINCT auf das count() reagiert, bzw ob es wie erwartet reagiert.
lg
Ludwig
Hi,
select DISTINCT count(personalnummer) from buchungen;
Sollte die summer von den personalnummern ausgeben, wobei jeder personalnummer nur einmal gezählt wird.
hmm, leider nicht und aus dem Ergebnis werd ich nicht so schlau.
Es wird was gezählt, es deutlich weniger angezeigt als ohne Distinct, aber was ... keine Ahnung.
tests are going on...
Knud
das ist die anzahl der User, die gebucht haben mindestens einmal gebucht haben.
Hi,
select DISTINCT count(personalnummer) from buchungen;
Sollte die summer von den personalnummern ausgeben, wobei jeder personalnummer nur einmal gezählt wird.
hmm, leider nicht und aus dem Ergebnis werd ich nicht so schlau.
Es wird was gezählt, es deutlich weniger angezeigt als ohne Distinct, aber was ... keine Ahnung.
tests are going on...
Knud
das ist die anzahl der User, die gebucht haben mindestens einmal gebucht haben.
kann eigentlich nicht sein.
mit
select personalnummer, count(*) from buchungen where ndatum like '2002-01%' group by personalnummer;
werden mir doch auch alle personalnummern gezeigt, die mindestens ein mal gebucht haben (sonst wären sie auch nicht in der Tabelle *g*).
Mit dem DISTINCT sinds deutlich weniger und ich kann halt nicht erkennen warum gerade die angezeigt werden.
Gruß,
Knud
ja aber mit distinct verhindert man, das User doppelt angezeigt werden, und so wie ich es aus deiner frage erlesen habe, wolltest du alle user haben die gebucht haben und eine Mehrfachausgabe soll verhindert werden und das geht mit distinct.
das ist die anzahl der User, die gebucht haben mindestens einmal gebucht haben.
kann eigentlich nicht sein.
mit
select personalnummer, count(*) from buchungen where ndatum like '2002-01%' group by personalnummer;
werden mir doch auch alle personalnummern gezeigt, die mindestens ein mal gebucht haben (sonst wären sie auch nicht in der Tabelle *g*).
Mit dem DISTINCT sinds deutlich weniger und ich kann halt nicht erkennen warum gerade die angezeigt werden.
Gruß,
Knud
ja aber mit distinct verhindert man, das User doppelt angezeigt werden, und so wie ich es aus deiner frage erlesen habe, wolltest du alle user haben die gebucht haben und eine Mehrfachausgabe soll verhindert werden und das geht mit distinct.
und genau das macht doch auch schon das count mit dem group by, oder etwa doch nicht?
mit fragendem Blick,
Knud
Hallo Curt
und genau das macht doch auch schon das count mit dem group by, oder etwa doch nicht?
nein
deine Abfrage:
select personalnummer, count(*) from buchungen where ndatum like '2002-01%' group by personalnummer;
gibt an, welche Personalnummer wieviele Buchungen vorgenommen hat. Du möchstest aber wissen, wieviele Personalnummern Buchungen vorgenommen haben. Dazu genügt es
select , count(distinct personalnummer) from buchungen where ndatum like '2002-01%';
anzugeben.
Noch ein Tipp: Verwende statt like lieber DATE_FORMAT. Das macht dich unabhängig von gespeicherten Datumsformaten. In deinem Beispiel könnte das z.B. so aussehen
select , count(distinct personalnummer) from buchungen where FATE_FORMAT(ndatum,'%c.%y)='1.02';
%c steht für Monatszahlen ohne führende Null und %y für zweistellige Jahreszahlen.
Trennzeichen (hier der Punkt) ist beliebig. Mehr dazu http://mysql.com/documentation/mysql/bychapter/manual_Reference.html#Date_and_time_functions
Viele Grüße
Antje
Hi Antje,
Noch ein Tipp: Verwende statt like lieber DATE_FORMAT.
mein Stil wäre auch das nicht.
Ich will doch nicht in einer WHERE-Klausel, die vielleicht ein paar
Millionen mal ausgewertet wird, eine Konvertierungsfunktion aufrufen.
Womöglich schalte ich auf diese Weise sogar einen ansonsten möglichen
Indexzugriff implizit aus! Dann kann mich der Spaß einen Faktor an 1000
und mehr an Performance kosten.
Ich würde dazu tendieren, das Datum als UNIX time stamp (32 bit unsigned
integer) zu speichern, in meinem 3GL-Anwendungsprogramm die Konvertierung
zwischen welchem externen Datumsformat auch immer und diesem time stamp
durchführen und dann einfach einen Zahlenvergleich machen.
Falls ich ein festes Tagesraster benötige, dann kann ich ja die Zeitpunkte
jeweils auf 00:00:00 Uhr fixieren.
Das macht dich unabhängig von gespeicherten Datumsformaten.
Yep, aber meine Methode auch.
Datumsformate sind Visualisierungen, die will ich aus der Datenbank
komplett heraus halten.
Viele Grüße
Michael
Hi,
select DISTINCT count(personalnummer) from buchungen;
Sollte die summer von den personalnummern ausgeben, wobei jeder personalnummer nur einmal gezählt wird.
hmm, leider nicht und aus dem Ergebnis werd ich nicht so schlau.
Es wird was gezählt, es deutlich weniger angezeigt als ohne Distinct, aber was ... keine Ahnung.
was willst du jetzt als ergebniss ? Die anzahl ( = 1 zahl) der personen die etwas gebucht haben, bzw welche in der tabelle stehen ?
zu meinen obigen sql statement man könnte auch mal:
select count(distinct personalnummer) from buchungen; versuchen...
Distinct bewirkt das ein wert nur einmal verwendet wird. count zählt dann diese werte zusammen, das ergebniss sollte die menge der personen sein die mindestens eine buchung gemacht haben.
lg
Ludwig
Hi Ludwig
wie gesagt UNTESTED, ich weiß nicht wie DISTINCT auf das count() reagiert, bzw ob es wie erwartet reagiert.
Gemäss MySQL Manual: http://www.mysql.com/doc/D/I/DISTINCT_optimisation.html
wird daraus ein Group By auf allen Spalten, also in dem Fall auf count()
weil es die einzige Spalte im Ergebnis ist. Es dürfte also keinerlei
Einfluss ausser dem Ausbremsen der Query (falls MySQL nicht automatisch
wegoptimiert) haben.
Gruss Daniela