skunk210480: Ranking - Zeile ermitteln MySQL 4.0.14

Hallo...

ich habe eine Tabelle wo die Gesamtpunkte meiner User gespeichert werden, so ungefaehr

|user|punkte|
-------------
|1   |500   |
|2   |700   |
|3   |600   |

alle 24 Stunden wird diese Tabelle nun mit "ALTER TABLE tabelle ORDER BY punkte DESC" sortiert, sodas die Tabelle nun wie folgt aussieht...

|user|punkte|
|2   |700   |
|3   |600   |
|1   |500   |

wenn ich nun per "SELECT * FROM tabelle WHERE user = 1" den Eintrag selektiere, moechte ich gern wissen, der wievielte Datensatz dieser ist.
Mit "LIMIT" kann ich MySQL sagen welchen Datensatz er selektieren soll... ich moechte aber wissen den wievielten Datensatz ich selektiert habe. Also eigentlich genau andersherum.

MfG skunk210480

  1. Moin!

    alle 24 Stunden wird diese Tabelle nun mit "ALTER TABLE tabelle ORDER BY punkte DESC" sortiert, sodas die Tabelle nun wie folgt aussieht...

    Wozu dies? MySQL kann doch auch direkt bei der Abfrage sortieren.

    wenn ich nun per "SELECT * FROM tabelle WHERE user = 1" den Eintrag selektiere, moechte ich gern wissen, der wievielte Datensatz dieser ist.

    Zähl bei der Ausgabe mit, wieviele Datensätze du schon ausgegeben hast. Diese Info stellt dir die Datenbank nicht zur Verfügung.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
    1. Wozu dies? MySQL kann doch auch direkt bei der Abfrage sortieren.

      Hallo... das schon, aber nur temporaer, das heisst das bei jeder Abfrage die Tabelle sortiert wird. Sehr ineffektiv bei 5000 User oder so, die theoretisch alle gleichzeitig die Tabelle sortieren lassen koennten.

      Zähl bei der Ausgabe mit, wieviele Datensätze du schon ausgegeben hast. Diese Info stellt dir die Datenbank nicht zur Verfügung.

      Auch das ist sehr ineffektiv, da der 5000. User dann eine Zaehlschleife von 5000 Runden haette... obwohl ich nur wissen will das es der 5000. Eintrag ist.

      Ok... wenn das nicht gehen sollte, dann sollte sich jemand mit Erfahrung und Wissen daran machen, solch eine Funktion zu bauen.

      Trotzdem danke fuer die Antwort

      MfG skunk210480

      1. Moin!

        Wozu dies? MySQL kann doch auch direkt bei der Abfrage sortieren.

        Hallo... das schon, aber nur temporaer, das heisst das bei jeder Abfrage die Tabelle sortiert wird. Sehr ineffektiv bei 5000 User oder so, die theoretisch alle gleichzeitig die Tabelle sortieren lassen koennten.

        Sprich bitte nicht von "ineffektiv" bei so winzigen Datensatzzahlen!

        Abgesehen davon: Wenn du nur einmal in 24 Stunden sortierst - was ist dann in der Zwischenzeit, wenn sich Punktezahlen mal ändern? Oder existiert dieser Fall nicht?

        Zähl bei der Ausgabe mit, wieviele Datensätze du schon ausgegeben hast. Diese Info stellt dir die Datenbank nicht zur Verfügung.

        Auch das ist sehr ineffektiv, da der 5000. User dann eine Zaehlschleife von 5000 Runden haette... obwohl ich nur wissen will das es der 5000. Eintrag ist.

        Wenn du alle 5000 User ausgibst, mußt du ja sowieso die 4999 davor auch zählen. Wenn du nur einen selektiven Ausschnitt (4990 - 5000) abfragst, kannst du den Offset vorbelegen.

        Und wenn du tatsächlich nur an einem einzigen Datensatz interessiert bist, kannst du dessen Positionierung natürlich auch aus der Datenbank abfragen, indem du die Anzahl der Datensätze ausgeben läßt, die mehr Punkte haben als der gefragte User.

        Ok... wenn das nicht gehen sollte, dann sollte sich jemand mit Erfahrung und Wissen daran machen, solch eine Funktion zu bauen.

        Datenbanken verwalten absichtlich unsortierte Datenbestände, die nur im Bedarfsfall sortiert werden. Insofern existiert kein "der erste Datensatz", weil das je nach Sortierung und Abfragebedingungen jeder Datensatz sein könnte. Je größer die Datenmengen, desto uninteressanter wird diese Fragestellung auch - bei Ranglisten natürlich nicht. Deshalb aber in Datenbanken spezielle Funktionen einzubauen, die einfach nur zählen, wäre irgendwie blöd. Zumal die ja auch nichts anderes machen können, als von 1 loszuzählen und bei 5000 oder 5 Millionen anzukommen, auch wenn du nur den 5millonsten Eintrag haben wolltest.

        - Sven Rautenberg

        --
        "Love your nation - respect the others."
        1. Sprich bitte nicht von "ineffektiv" bei so winzigen Datensatzzahlen!

          Es ist schon etwas ineffizient, zwei Abfragen täten den Job sicherlich besser.

          Abgesehen davon: Wenn du nur einmal in 24 Stunden sortierst - was ist dann in der Zwischenzeit, wenn sich Punktezahlen mal ändern? Oder existiert dieser Fall nicht?

          Sinnloses Sortieren per Job, das ist wirklich nicht gut.

          1. Abgesehen davon: Wenn du nur einmal in 24 Stunden sortierst - was ist dann in der Zwischenzeit, wenn sich Punktezahlen mal ändern? Oder existiert dieser Fall nicht?

            Sinnloses Sortieren per Job, das ist wirklich nicht gut.

            Danke erstmal fuer die Antwort...

            ja gut... wenn die Abfrage die Zeilennummer nicht liefern kann dann brauch ich auch nicht zu sortieren... das ist schon klar. Aber wieso per Job? Es ist doch nur ein einmaliges "ALTER TABLE". Das kann ich doch mit in die index nehmen.

            Aber ich hab bei MySQL 5 gelesen, das es dort eine API-Funktion "mysql_row_tell()" gibt. Die macht sowas anscheinend, aber ab wann wurde die in PHP mit uebernommen?

            MfG skunk210480

            1. Aber ich hab bei MySQL 5 gelesen, das es dort eine API-Funktion "mysql_row_tell()" gibt. Die macht sowas anscheinend, aber ab wann wurde die in PHP mit uebernommen?

              Mach einfach zwei Abfragen, die eine holt Dir die "Stammdaten" zu einem Datensatz, die zweite holt Dir den Platz.

              Auf keinen Fall alle Datensätze vom Datenserver holen und damit irgendwie rummachen wie weiter oben vorgeschlagen.

              Wenn Du den regelmässig ausgeführten Aktualisierungsjob auch nicht mehr so toll findest:
              Was ist Dir eigentlich noch unklar?

      2. Hello,

        wenn du sowieso eine vorher festgelegte Aktion auf der Datensatzmenge ausführst, warum vergibst du die Datensatznummer nicht einfach mit - eine Spalte vom Typ Integer wird deine Datenbank kaum umbringen...

        MfG
        Rouven

        --
        -------------------
        Computer programming is tremendous fun. Like music, it is a skill that derives from an unknown blend of innate talent and constant practice. Like drawing, it can be shaped to a variety of ends: commercial, artistic, and pure entertainment. Programmers have a well-deserved reputation for working long hours but are rarely credited with being driven by creative fevers. Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination, but because their imagination reveals worlds that others cannot see. -- Larry OBrien and Bruce Eckel in Thinking in C#
        1. wenn du sowieso eine vorher festgelegte Aktion auf der Datensatzmenge ausführst, warum vergibst du die Datensatznummer nicht einfach mit - eine Spalte vom Typ Integer wird deine Datenbank kaum umbringen...

          Hallo...

          hab zwar erst nicht verstanden wie du das meinst, aber stimmt, wenn ich die Platzierung mit in den Datensatz nehme und bei der Aktualisierung in der Schleife die Platzierung "UPDATE" dann koennte man nachfolgend direkt den User mit der Platzierung selektieren.

          Nur weiss ich nicht in wie fern sonn 5000-facher "UPDATE" sich auf die Performance ausmacht.

          Achso... wahrscheinlich wuerde die Aktualisierung wohl eher auf alle 10 Minuten hinauslaufen.

          Danke fuer den Tipp!

          MfG skunk210480

  2. alle 24 Stunden wird diese Tabelle nun mit "ALTER TABLE tabelle ORDER BY punkte DESC" sortiert, ...

    Das ist Quatsch, vermutlich haben dir die Kollegen das schon erklärt.

    |user|punkte|
    |2   |700   |
    |3   |600   |
    |1   |500   |

    wenn ich nun per "SELECT * FROM tabelle WHERE user = 1"

    Da solltest Du mit Sub-SELECTs kommen, also bspw.:

      
    SELECT  
     *,              -- es ist oft besser die Datenfeldnamen zu benennen, also horizontal zu filtern (vertikales Filtern empfiehlt sich natürlich auch meist)  
     (  
     SELECT  
      COUNT(*)  
     FROM  
      Tabelle  
     WHERE  
      (  
      punkte >  
       (  
       SELECT  
        Punkte  
       FROM  
        Tabelle  
       WHERE  
        (  
        user = 1  
        )  
       )  
      ) AS Platz  
    FROM  
     Tabelle  
    WHERE  
     (  
     user = 1  
     )  
    
    

    PS: Sehe gerade MySQL 4, das kann vielleicht keine Sub-SELECTs.
    :-)