Seltsames Ergebnis MYSQL Abfrage
lachesis
- datenbank
Hallo,
ich möchte aus einer Tabelle, die ids der 10 zuletzt verwendeten projektnummern auselesen. Dazu verwende ich:
SELECT pid, datum, left(pname,20) as ppname, left(name,10) as nname,pnr
FROM stunden, projektnr, kunden
WHERE uid = $aktuser AND pid = projektnr.id AND kid = kunden.id
GROUP BY pid
ORDER BY datum DESC
LIMIT 10
Leider funktioniert das nicht... ich bekomme 10 Ergebnisse, leider 10 falsche...
suche ich von Hand nach den zuletzt verwendeten 10 krieg ich ein anderes (richtiges) Ergebnis, als meine obige Abfrage..
Scheinbar ist noch ein Fehler drin, aber welcher?
tabelle stunden
id
pid
uid
stunden
datum
pruef
gebucht
tabelle projektnr
id
pnr
pname
kid
iid
tabelle kunden
id
name
Halihallo lachesis
suche ich von Hand nach den zuletzt verwendeten 10 krieg ich ein anderes (richtiges) Ergebnis, als meine obige Abfrage..
Welche Abfrage führst du von Hand aus? - Hast du auch bei dieser nach pid gruppiert?
Denn da liegt meiner Glaskugel und schnell überfliegenden Augen nach der Fehler.
Viele Grüsse
Philipp
Welche Abfrage führst du von Hand aus? - Hast du auch bei dieser nach pid gruppiert?
DANKE!!!
Leih mir mal bitte Deine Glaskugel...
Ich habs geändert in:
SELECT DISTINCT pid, datum, left(pname,20) as ppname, left(name,10) as nname, pnr
FROM stunden, projektnr, kunden
WHERE uid = $aktuser AND pid = projektnr.id AND kid = kunden.id
ORDER BY datum DESC
LIMIT 10
Was ja auch mehr Sinn macht...
Und siehe da es funktioniert!
Danke und CLOSED
Und siehe da es funktioniert!
*umpf* nein es funzt nicht so ganz...
Ich hab jetzt doppelte Einträge... aber warum???? *grübel*
Sollte DISTINCT nicht dafür sorgen, dass ich jede pid nur einmal finde?
SORRY, ich hab grade erst mit sql und php angefangen
Halihallo lachesis
Und siehe da es funktioniert!
*umpf* nein es funzt nicht so ganz...
Ich hab jetzt doppelte Einträge... aber warum???? *grübel*
Was sagt _deine_ Kristallkugel? - Hm, ich glaube, wenn sie schweigt braucht sie ein
http://www.mysql.com/doc/en/DISTINCT_optimisation.html oder
http://www.mysql.com/doc/en/SELECT.html update!
Und? - Gefunden?
Sollte DISTINCT nicht dafür sorgen, dass ich jede pid nur einmal finde?
Wieso sollte DISTINCT, bitteschön?
SORRY, ich hab grade erst mit sql und php angefangen
Genau _deshalb_ sollst du die Dokus lesen, Herr Gott! :-)
Viele Grüsse
Philipp
PS: Ich/wir lese(n) auch Threads mit "DANKE", gerne sogar, no need to copy anything.
Wieso sollte DISTINCT, bitteschön?
OK,
DISTINCT verhindert doppelte zeilen.. da sich das Datum ändert findet er eine pid zweimal an verschiedenen Tagen...
hab ich verstanden...
aber ich hab nicht verstanden wie ich mein Ausgangsproblem löse...
wenn ich das richtig verstehe hört mysql auf, sobald dem limit entsprechend viele Zeilen gefunden wurden... und sortiert erst dann das Ergebnis nach Datum... right?
wie kann ich denn erst sortieren und dann nur die ersten 10 ausgeben?
Sorry für meine Erkenntnisrsistenz
Halihallo lachesis
DISTINCT verhindert doppelte zeilen.. da sich das Datum ändert findet er eine pid zweimal an verschiedenen Tagen...
Aha! - Kleiner aber wesentlicher Unterschied ;)
wenn ich das richtig verstehe hört mysql auf, sobald dem limit entsprechend viele Zeilen gefunden wurden... und sortiert erst dann das Ergebnis nach Datum... right?
Ne, anders rum. MySQL sortiert nach Datum, distinctiviert die Datensätze und erst
dann liefert LIMIT die Anzahl Datensätze (etwas leienhaft ausgedrückt, die Realität
sieht etwas komplizierter aus).
wie kann ich denn erst sortieren und dann nur die ersten 10 ausgeben?
Was möchtest du _genau_? - Denn das, was du wünschst, hast du bereits vollbracht.
(so weit ich sehe, macht deine SQL-Abfrage genau das).
Viele Grüsse
Philipp
Was möchtest du _genau_? - Denn das, was du wünschst, hast du bereits vollbracht.
(so weit ich sehe, macht deine SQL-Abfrage genau das).
hm, also wenn ich:
SELECT DISTINCT pid, datum, left( pname, 20 ) AS ppname, left( name, 10 ) AS nname, pnr
FROM stunden, projektnr, kunden
WHERE uid = 7 AND pid = projektnr.id AND kid = kunden.id
ORDER BY datum DESC
LIMIT 10
in phpmyadmin absetze krieg ich als ergebnis:
116 2003-05-22 Amplitudenselektiver Sachs 560053E000-000
116 2003-05-21 Amplitudenselektiver Sachs 560053E000-000
113 2003-05-20 Rechteckmanschette BSH Bosch temp
88 2003-05-20 Manschette Weiterent BSH Bosch 105541E000-000
5 2003-05-20 Sonstiges Intern 05
113 2003-05-19 Rechteckmanschette BSH Bosch temp
5 2003-05-19 Sonstiges Intern 05
113 2003-05-16 Rechteckmanschette BSH Bosch temp
112 2003-05-16 Federbeinkopflager P WMAVS 500102E000-000
112 2003-05-15 Federbeinkopflager P WMAVS 500102E000-000
ok, das versteh ich
was ich möchte ist aber, dass eine pid nur ein mal vorkommt.
Also hab ich mir gedacht, dass das group by pid dies tun könnte.
Leider krieg ich mit group by:
116 2003-05-21 Amplitudenselektiver Sachs 560053E000-000
113 2003-05-16 Rechteckmanschette BSH Bosch temp
111 2003-05-09 Abaqus Rechnung f. D WMAVS 580033E000-004
110 2003-05-09 Soundgenerator Rollm Daimler Ch 360437E002-000
112 2003-05-08 Federbeinkopflager P WMAVS 500102E000-000
108 2003-04-17 Weiterentwicklung VR Buderus - 100195P000-000
88 2003-04-01 Manschette Weiterent BSH Bosch 105541E000-000
4 2003-03-28 Urlaub Intern 04
18 2003-03-14 347 Transit Ford 520022E000-004
3 2003-03-13 EDV Intern 03
Du siehst es fehlt zB sonstiges...
Das Datum zu Rechteck ist nicht das letzte...
Sorry ich steh ziemlich aufm Schlauch
Halihallo lachesis
was ich möchte ist aber, dass eine pid nur ein mal vorkommt.
Also hab ich mir gedacht, dass das group by pid dies tun könnte.
Die Frage ist: Wenn du nach pid gruppierst, was soll dann mit den zusammengezogenen
Daten passieren? - Willst du pro pid das kleinste, das grösste oder die Summe der
Daten (letzteres, naja...). Wenn du GROUP BY benutzt, _musst_ du für jede _nicht_
Gruppierte Spalte sogenannte Agregatsfunktionen anwenden. Diese findest du in
http://www.mysql.com/doc/en/Group_by_functions.html, ansonsten weiss MySQL nicht,
was du denn überhaupt haben willst und fälschlicherweise liefert MySQL dann einfach
"irgendwas".
Folgendes Szenario:
Du hast eine Tabelle X:
id datum test
001 2003-05 hello world
002 2002-06 foo
003 2003-07 foo
001 2003-02 bar2
Nun führst du folgende Abfrage aus:
SELECT id, datum, test FROM X GROUP BY id
und kriegst:
id datum test
001 ??? ???
002 2002-06 foo
003 2003-07 foo
Jede id kommt aufgrund des GROUP BY id nur einmal vor. Bei id=002|003 ist auch das
ausgeben von datum und test "kein Problem", da die id nur einmal vorkommt, was aber bei
id=001? - id 001 kommt zweimal vor, es werden also zwei Datensätze zu einem zusammenge-
zogen. Was soll MySQL jetzt bitte schön deiner Meinung nach als datum oder test aus-
geben? - Wie soll es wissen, welches der beiden Daten und tests du nun möchtest?
Genau dieses Problem wird duch die Agregationsfunktionen gelöst; es ist dort möglich z.B.
das "maximale" (MAX(datum)) Datum aus den zwei zusammengezogenen Daten zu selektieren.
Du siehst es fehlt zB sonstiges...
GROUP BY pid führt dazu, dass alle Datensätze mit gleicher pid zusammengezogen werden.
Da du keine Agregatsfunktionen verwendest, weiss MySQL nicht, welches datum du aus
den zusammengezogenen Records extrahieren willst. Nimmt MySQL bei pid=5 (sonstiges) nun
ein ganz altes Datum (in deiner Datenbank kommt pid=5 nicht nur einmal vor, wie ich
folgere), fällt es aus den ersten 10 heraus (wird bei GROUP BY pid nicht mehr aus-
gegeben).
Das Datum zu Rechteck ist nicht das letzte...
s. oben. Woher soll MySQL wissen, welches Datum du willst? - Das erste (maximale)? -
Das letzte (kleinste, älteste)?
Sorry ich steh ziemlich aufm Schlauch
Kleiner Tipp: Datenbanken sind (multi-)mengenorientiert und es sind nach der 1NF keine
mehrwertigen Attribute erlaubt. Das Zusammenziehen von Records (GROUP BY) impliziert
dies jedoch (eine pid hat plötzlich mehrere Daten, wenn die pid mehrmals definiert ist).
Ausweg sind die genannten Agregatsfunktionen, andernfalls muss die DBMS raten, was
_immer_ schlecht ist (und meiner Meinung nach ein Bug im System ist).
Zuerst wird die Menge des Ergebnisses gebildet, dann wird Gruppiert, dann wird
Sortiert und am Schluss wird LIMIT ausgeführt. Die Datenbank sortiert völlig korrekt, nur
sortiert sie eine falsch abgebildete Menge (falsch, weil dessen Abbildungsvorschrift
nicht eindeutig war => bei GROUP BY keine Agregationsfunktionen).
So, das hätte ich mal wieder gesagt und ich hoffe, dass dir die "Phänomene" jetzt
logisch erklärbar sind...
Viele Grüsse und HTH
Philipp
Halihallo lachesis
Viele Grüsse und HTH
HTH??
Philipp
Oh mann, dankeschön mit:
SELECT pid, left(pname,20) as ppname, left(name,10) as nname, pnr, max(datum) as maxdatum
FROM stunden, projektnr, kunden
WHERE uid = $aktuser AND pid = projektnr.id AND kid = kunden.id
GROUP by pid
ORDER BY maxdatum DESC
LIMIT 10
funktionierts einwandfrei....
Das ganze ist dann doch ziemlich kompliziert für einen Newbie wie mich..
DANKE!!!
Halihallo lachesis
Viele Grüsse und HTH
HTH??
Hast du danach schon über google gesucht? - Hope That Helps again :-)
Das ganze ist dann doch ziemlich kompliziert für einen Newbie wie mich..
<altklug>
Keine Sorge, das legt sich mit der Zeit :-)
</altklug>
Viele Grüsse
Philipp
Und siehe da es funktioniert!
*umpf* nein es funktioniert nicht so ganz...
Ich hab jetzt doppelte Einträge... aber warum???? *grübel*
Sollte DISTINCT nicht dafür sorgen, dass ich jede pid nur einmal finde?
SORRY, ich hab grade erst mit sql und php angefangen