Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] [MySQL] Tabelle nach zwei Kriterien sortieren

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] [MySQL] Tabelle nach zwei Kriterien sortieren

    Hallo zusammen,

    ich habe eine Tabelle namens "counter" mit den folgenden Spalten: ID, wertung, datum & counter.

    Die Daten, die dort gespeichert werden sehen dann bspw. so aus: 1, 454, 2014-05-30, 5 etc.

    Folgendes möchte ich gerne erreichen: Ich möchte gerne für jeden Tag den Eintrag mit den meisten Hits/dem höchsten Counter ausgegeben bekommen, sortiert nach dem letzten Datum (2014-05-30, dann 2014-05-29 etc.).

    Mit
    PHP-Code:
    GROUP BY `datum
    erreiche ich ja schon einmal, dass ich ein Datum bloß einmal erhalte.
    Wenn ich später im Query noch
    PHP-Code:
    ORDER BY `datumDESC 
    angebe, bekomme ich ja die gewünschte Reihenfolge.

    Mein Problem ist nun, dass der höchste Wert nicht angezeigt wird, sondern einfach der erste, der zum nächsten Tag gehört.


    Kann ich dies innerhalb eines Queries lösen?
    Hat jemand eine Idee - vielen Dank!

  • #2
    Code:
    select datum, sum(wert) from tmp group by datum order by datum desc
    [URL="https://github.com/chrisandchris"]GitHub.com - ChrisAndChris[/URL] - [URL="https://github.com/chrisandchris/symfony-rowmapper"]RowMapper und QueryBuilder für MySQL-Datenbanken[/URL]

    Kommentar


    • #3
      Vielen Dank für die Antwort, jedoch bringt dies leider nicht das, was ich schon die ganze Zeit versuche.

      Ich versuche es nochmal anders zu erklären, wie die Datenstruktur aussieht, bspw. so:
      ID, wertung, datum, counter
      1, 455, 2014-05-30, 5
      2, 894, 2014-05-30, 16
      3, 212, 2014-05-30, 3

      D.h. dann soll beim 30.05.2014 nur der Tupel mit der ID 2 & dem Counter 16 angezeigt werden.


      Vielen Dank!

      Kommentar


      • #4
        Dann benutz halt ein Limit.
        [COLOR="#F5F5FF"]--[/COLOR]
        [COLOR="Gray"][SIZE="6"][FONT="Georgia"][B]^^ O.O[/B][/FONT] [/SIZE]
        „Emoticons machen einen Beitrag etwas freundlicher. Deine wirken zwar fachlich richtig sein, aber meist ziemlich uninteressant.
        [URL="http://www.php.de/javascript-ajax-und-mehr/107400-draggable-sorttable-setattribute.html#post788799"][B]Wenn man nur Text sieht, haben viele junge Entwickler keine interesse, diese stumpfen Texte zu lesen.“[/B][/URL][/COLOR]
        [COLOR="#F5F5FF"]
        --[/COLOR]

        Kommentar


        • #5
          Dafür wirst du (soweit ich weiß) einen Subquery benötigen, da du extra diesen maximalen Counter für das jeweilige Datum heraussuchen musst:

          Code:
          SELECT `c`.*
          FROM `counter` `c`
          INNER JOIN (
              SELECT MAX(`counter`) AS `max`
              FROM `counter`
              GROUP BY `datum`
          ) `m` ON `m`.`max` = `c`.`counter`
          GROUP BY `datum`;

          Kommentar


          • #6
            Zitat von chris. Beitrag anzeigen

            Code:
            select `c`.*
            ...
            Group by `datum`;

            fail.
            PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

            Kommentar


            • #7
              Vielen Dank für diese Idee, Chris.
              Leider bringt dies auch noch nicht den gewünschten Erfolg, da dann bspw. am heutigen Tag wieder der erste Tupel angezeigt wird, obwohl es inzwischen 3-4 weitere Tupel gibt, die einen größeren Wert haben.

              Kommentar


              • #8
                Zitat von NXTTakeOver Beitrag anzeigen
                Vielen Dank für diese Idee, Chris.
                Leider bringt dies auch noch nicht den gewünschten Erfolg, da dann bspw. am heutigen Tag wieder der erste Tupel angezeigt wird, obwohl es inzwischen 3-4 weitere Tupel gibt, die einen größeren Wert haben.
                Ich schenke Dir MAX().
                PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                Kommentar


                • #9
                  Die MAX()-Funktion ist super, ja.
                  Damit bekomme ich die tatsächlich benötigte Höchstzahl an Klicks heraus - jedoch will der Rest wie ID etc. nicht stimmen, da dies immer noch auf den ersten Eintrag am entsprechenden Tag liegt.

                  Kommentar


                  • #10
                    Zitat von NXTTakeOver Beitrag anzeigen
                    Die MAX()-Funktion ist super, ja.
                    Damit bekomme ich die tatsächlich benötigte Höchstzahl an Klicks heraus - jedoch will der Rest wie ID etc. nicht stimmen, da dies immer noch auf den ersten Eintrag am entsprechenden Tag liegt.
                    Das Result noch mal gegen die Ausgangstabelle joinen. In PG wäre es mit DISTINCT ON (...) einfacher.
                    PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                    Kommentar


                    • #11
                      Zitat von akretschmer Beitrag anzeigen
                      fail.
                      Code:
                      SELECT DISTINCT `c`.`id`,
                                      `c`.`wertung`, 
                                      `c`.`datum`,
                                      `c`.`counter`
                      FROM `counter` `c`
                      INNER JOIN (
                          SELECT MAX(`counter`) AS `max`
                          FROM `counter`
                          GROUP BY `datum`
                      ) `m`
                      ON (`m`.`max` = `c`.`counter`);
                      So scheint es besser zu sein.

                      Test:

                      Der Inhalt der Tabelle:

                      Code:
                      mysql> SELECT * FROM counter;
                      +----+---------+------------+---------+
                      | id | wertung | datum      | counter |
                      +----+---------+------------+---------+
                      |  1 |     500 | 2014-05-01 |      20 |
                      |  2 |     600 | 2014-05-01 |      21 |
                      |  3 |     500 | 2014-05-02 |      15 |
                      |  4 |     600 | 2014-05-02 |      21 |
                      +----+---------+------------+---------+
                      4 rows in set (0.00 sec)
                      Die Abfrage:

                      Code:
                      mysql> SELECT DISTINCT `c`.`id`, `c`.`wertung`, `c`.`datum`, `c`.`counter` FROM `counter` `c` INNER JOIN ( SELECT MAX(`counter`) AS `max` FROM `counter` GROUP BY `datum` ) `m` ON (`m`.`max` = `c`.`counter`);
                      +----+---------+------------+---------+
                      | id | wertung | datum      | counter |
                      +----+---------+------------+---------+
                      |  2 |     600 | 2014-05-01 |      21 |
                      |  4 |     600 | 2014-05-02 |      21 |
                      +----+---------+------------+---------+
                      2 rows in set (0.00 sec)
                      Ergebnis: Man erhält für jedes Datum jenen Datensatz mit dem maximalen Wert im Feld "counter".

                      Kommentar


                      • #12
                        Dies funktioniert, aber auch nur, wenn die Werte so gesetzt sind wie Du sie testweise gesetzt hast.

                        Wenn die Tabelle z.B. so aussieht, funktioniert es wiederum leider nicht mehr:

                        Denn dann bekommst Du folgendes Resultat:

                        Kommentar


                        • #13
                          Hatte ich nicht beachtet, guter Einwand. Könnte man so lösen (Zu beachten: Falls an einem Tag zwei Einträge mit gleichem Counter-Wert zur Verfügung stehen, werden auch beide Einträge zurückgegeben):

                          Code:
                          SELECT DISTINCT `c`.`id`,
                                          `c`.`wertung`, 
                                          `c`.`datum`,
                                          `c`.`counter`
                          FROM `counter` `c`
                          INNER JOIN (
                              SELECT MAX(`counter`) AS `max`, `datum`
                              FROM `counter`
                              GROUP BY `datum`
                          ) `m`
                          ON (`m`.`max` = `c`.`counter` AND `m`.`datum` = `c`.`datum`);

                          Kommentar


                          • #14
                            Jop, perfekt.

                            Stimmt, es gibt tatsächlich einige doppelte & Dreifacheinträge, sofern es an einem Tag mehrere Höchstwerte gab.

                            Mit LIMIT konnte ich da nichts erreichen, so dass bloß ein Resultat angezeigt wird.
                            Gibt es daher eine weitere Möglichkeit?

                            Kommentar


                            • #15
                              Wenn du die erste ID pro GROUP BY im Resultat stehen haben möchtest, dann hast du noch dazu die minimale ID (MIN()) pro GROUP BY herauszusuchen. Möchtest du die maximale ID, so ersetzt du MIN() durch MAX(). Wenn du n GROUP BY Datensätze im Resultat stehen haben möchtest, dann wird die Lösung komplexer, da dies eine bekannte MySQL-Hürde ist: http://www.xaprb.com/blog/2006/12/07...-group-in-sql/

                              Code:
                              SELECT MIN(`c`.`id`) AS `id`,
                                     `c`.`wertung`, 
                                     `c`.`datum`,
                                     `c`.`counter`
                              FROM `counter` `c`
                              INNER JOIN (
                                  SELECT MAX(`counter`) AS `max`, `datum`
                                  FROM `counter`
                                  GROUP BY `datum`
                              ) `m`
                              ON (`m`.`max` = `c`.`counter` AND `m`.`datum` = `c`.`datum`)
                              GROUP BY `datum`;
                              P.S.: DISTINCT ist nun nicht länger von Nöten und kann daher entfernt werden.

                              Kommentar

                              Lädt...
                              X