lachesis: Seltsames Ergebnis MYSQL Abfrage

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

--
mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
  1. 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

    --
    RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
    Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    1. 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

      --
      mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
      1. 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

        --
        mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
        1. 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.

          --
          RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
          Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
          1. 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

            --
            mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
            1. 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

              --
              RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
              Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
              1. 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

                --
                mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
                1. 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

                  1. 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!!!

                    --
                    mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.
                    1. 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

                      --
                      RTFM! - Foren steigern das Aufkommen von Redundanz im Internet, danke für das lesen der Manuals.
                      Selbstbedienung! - Das SelfForum ist ein Gratis-Restaurant mit Selbstbedienung, Menüangebot steht in den </faq/> und dem </archiv/>.
    2. 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

      --
      mal wieder auf http://www.booklinks.de vorbeigeschaut? Mittlerweile mehr als 800! Bücher.