Günther S: GROUP BY-Queries

Hallo,

ich habe eine Frage zu MySQL Anfragen nach dem Muster

SELECT user_id, punktzahl FROM punkte GROUP BY user_id

Gehen wir aber zunächst mal davon aus, dass die Anfrage

SELECT user_id, punktzahl FROM punkte (also ohne GROUP BY)

folgende Ergebnisse liefert:

user_id | punktzahl
-------------------
1       | 2        # zurückgelieferte Zeile
1       | 5
1       | 1
1       | 4        # gewünschte Zeile
2       | 5        # zurückgelieferte Zeile
2       | 0
2       | 2        # gewünschte Zeile

Mit dem GROUP BY wird das auf Folgendes reduziert:

user_id | punktzahl
-------------------
1       | 2
2       | 5

Gibt es eine Möglichkeit, die zurückgelieferten Werte derjenigen Spalten zu beeinflussen, die nicht bei GROUP BY stehen?

Gewünscht wäre z.B. folgende Ergebnismenge:

user_id | punktzahl
-------------------
1       | 4
2       | 2

(siehe auch erste Ergebnismenge in diesem Post)

Ist das irgendwie möglich?

Gruß,
Günther

  1. Hi,

    ich habe eine Frage zu MySQL Anfragen nach dem Muster
    SELECT user_id, punktzahl FROM punkte GROUP BY user_id

    tja, andere DBMSse hätten dieses Statement als fehlerhaft abgelehnt. Warum MySQL krampfhaft versucht, da irgend etwas draus zu machen, ist mir nach wie vor absolut schleierhaft.

    1       | 4        # gewünschte Zeile

    _Warum_ ist diese Zeile gewünscht?

    Gibt es eine Möglichkeit, die zurückgelieferten Werte derjenigen Spalten zu beeinflussen, die nicht bei GROUP BY stehen?

    Du musst(!) nach *allen* Spalten gruppieren, die nicht durch eine Gruppenfunktion wie z.B. SUM() oder MAX() erzeugt werden. Tust Du dies nicht, gibt das gewöhnlich einen Fehler, bei MySQL hingegen irgendwas.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:° br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hallo,

      _Warum_ ist diese Zeile gewünscht?

      Ich benötige jeweils die letzte eingetragene Punktzahl jedes Users. Das muss aber nicht zwangsläufig die größte oder kleinste sein und schon gar nicht der Durchschnitt aller Punktzahlen des Users.

      Du musst(!) nach *allen* Spalten gruppieren, die nicht durch eine Gruppenfunktion wie z.B. SUM() oder MAX() erzeugt werden. Tust Du dies nicht, gibt das gewöhnlich einen Fehler, bei MySQL hingegen irgendwas.

      Aha, gut zu wissen!

      Gruß,
      Günther

      1. Hi,

        Ich benötige jeweils die letzte eingetragene Punktzahl jedes Users.

        Hast Du denn überhaupt eine Spalte, die definiert, welche Punktzahl die letzte eingetragene ist (also z.B. den Zeitpunkt oder ähnliches)?
        Oder woran willst Du das "letzte eingetragene" festmachen?

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        Schreinerei Waechter
        O o ostern ...
        Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
        1. Hallo,

          Hast Du denn überhaupt eine Spalte, die definiert, welche Punktzahl die letzte eingetragene ist (also z.B. den Zeitpunkt oder ähnliches)?

          Ja, Datum und Uhrzeit wird bei jedem Datensatz gespeichert - habe ich vergessen zu erwähnen, entschuldige bitte.
          Sortierung nach DATETIME-Spalte wäre also möglich, um das herauszufinden.

          Gruß,
          Günther

          1. Hallo Günther,

            Ja, Datum und Uhrzeit wird bei jedem Datensatz gespeichert - habe ich vergessen zu erwähnen, entschuldige bitte.

            und welche MySQL-Version?

            Sortierung nach DATETIME-Spalte wäre also möglich, um das herauszufinden.

            Sortierung ist "irrelevant":

            Beispiel:

            user_id | punktzahl | zeit
            ----------------------------------------
            1       | 2         | 12.10.2006 14:30
            1       | 5         | 02.11.2006 08:40
            1       | 1         | 27.04.2006 22:00
            1       | 4         | 08.01.2006 14:47
            2       | 5         | 17.06.2006 11:26
            2       | 0         | 22.10.2006 11:26
            2       | 2         | 17.12.2006 11:26

            SELECT  
                p1.user_id,  
                p1.punktzahl,  
                p1.zeit  
            FROM punkte p1                     -- Aliasnamen für die Tabelle punkte, auf  
                                               -- die "außen" wie "innen" zugegriffen wird  
            WHERE zeit = (  
                SELECT MAX(p2.zeit)            -- Suche den neuesten Zeitpunkt  
                FROM punkte p2                 --  
                WHERE p1.user_id = p2.user_id  -- für jeden Benutzer  
            )
            

            Ergebnis:

            user_id | punktzahl | zeit
            ----------------------------------------
            1       | 4         | 08.01.2006 14:47
            2       | 2         | 17.12.2006 11:26

            Ein ganz normales korreliertes Subselect, wie von mir bereits verlinkt.

            Voraussetzung: MySQL 4.1 und neuer.

            Freundliche Grüße

            Vinzenz

            1. Hallo,

              und welche MySQL-Version?

              5.x

              SELECT

              p1.user_id,
                  p1.punktzahl,
                  p1.zeit
              FROM punkte p1                     -- Aliasnamen für die Tabelle punkte, auf
                                                 -- die "außen" wie "innen" zugegriffen wird
              WHERE zeit = (
                  SELECT MAX(p2.zeit)            -- Suche den neuesten Zeitpunkt
                  FROM punkte p2                 --
                  WHERE p1.user_id = p2.user_id  -- für jeden Benutzer
              )

              Manchmal sieht man den Wald vor lauter Bäumen nicht. Danke für deine Hilfe!  
                
              Gruß,  
              Günther
              
      2. Hallo Günther,

        _Warum_ ist diese Zeile gewünscht?
        Ich benötige jeweils die letzte eingetragene Punktzahl jedes Users. Das muss aber nicht zwangsläufig die größte oder kleinste sein und schon gar nicht der Durchschnitt aller Punktzahlen des Users.

        die Standardlösung für dieses Problem sind korrelierte Unterabfragen, siehe z.B. dieses Archivposting.
        Unterabfragen unterstützt MySQL ab Version 4.1.

        <gebetsmühle>
            Bei Fragen zu MySQL ist es eine gute Idee, die verwendete Version
            anzugeben, da sich die Fähigkeiten von MySQL zwischen den Versionen
            zum Teil sehr stark unterscheiden.
        </gebetsmühle>

        Freundliche Grüße

        Vinzenz