Florian M.: RAND() bei MySQL funktioniert nicht richtig

Guten morgen,

ich lese zur Zeit Zitate aus einer MySQL Datenbank über RANDOM aus.
SELECT * FROM tabelle ORDER BY RAND() LIMIT 1

Es existieren ungefähr 40 - 50 Zitate in der Tabelle. Nun möchte ich,
dass nach jedem "Refresh" des Browser ein zufälliges Zitat aus der
Datenbank ausgelesen wird. Dies funktioniert nur teilweise, bzw. nicht
zufriedenstellend. Das Zitat, das ich als erstes in die Datenbank eingetragen
habe erscheint zu 90% immer als erstes Zitat und kommt nach jedem 3
bzw. 4 Bilder. Das ist für mich kein Zufall mehr.
Woran könnte dies liegen?

Danke schon einmal für Eure Hilfe.

Florian

  1. Hi,

    Woran könnte dies liegen?

    ich hab mal was ganz absurdes getan: nämlich die Doku zu Rate gezogen. Dort steht:

    """
    RAND()
    RAND(N)
        Returns a random floating-point value in the range 0 to 1.0. If an integer argument N is specified, it is used as the seed value:

    mysql> SELECT RAND();
            -> 0.9233482386203
    mysql> SELECT RAND(20);
            -> 0.15888261251047
    mysql> SELECT RAND(20);
            -> 0.15888261251047
    [...]
    """

    Wenn man sich die letzten zwei ausgespuckten Werte ansieht und bedenkt, dass auch Du einzelne Statements absetzt, sollte die Verwunderung sinken.

    Cheatah

    --
    X-Will-Answer-Email: No
    1. Hallo,

      danke für Deine Antwort. Welche alternativen bieten sich mir nun?
      Könntest Du Deine Aussage etwas konkretisieren. DANKE !!!

      bis denn

      Florian

      1. Hi,

        danke für Deine Antwort. Welche alternativen bieten sich mir nun?

        füttere RAND() aus der umgebenden Programmlogik (PHP?) mit einem von MySQL unabhängigen Zufallswert.

        Cheatah

        --
        X-Will-Answer-Email: No
  2. Hi Florian M.,

    Nun möchte ich, dass nach jedem "Refresh" des Browser ein zufälliges Zitat
    aus der Datenbank ausgelesen wird.

    nein, das möchtest Du nicht - denn diesen Zustand hast Du bereits.

    Dies funktioniert nur teilweise, bzw. nicht zufriedenstellend.

    Ich vermute, dies liegt zum Teil auch daran, daß Deine Aufgabenstellung in Wirklichkeit eben nicht "zufällige" Treffer haben will, sondern in erster Priorität ein bestimmtes Verteilungsverhalten im n-dimensionalen Raum wünscht und erst in zweiter Priorität die zufällige Auswahl.

    Wenn Du die Wahrscheinlichkeit für aufeinanderfolgende identische Treffer kontrollieren willst, dann würde ich an Deiner Stelle vorschlagen, Dich vom Lotto-Modell inspirieren zu lassen und Kugeln aus einer Urne zu ziehen - ohne Zurücklegen. Also keine zufälligen Zitate, sondern zufällige Anordnungen der Liste sämtlicher Zitate.
    Ich würde an Deiner Stelle ein Gedächtnis verwenden und darin speichern, welche Zitate im aktuellen "Durchgang" bereits "gezogen" wurden und welche noch nicht. In dem Moment, in welchem die Urne leer wird, füllst Du wieder alle Kugeln hinein. Auf diese Weise werden alle Kugeln gleich oft gezogen, es ist auch zufällig, in welcher Reihenfolge, aber es kommen nun keine Häufungen mehr vor.
    Es kann immer noch passieren, daß die letzte Kugel aus Durchgang <n> identisch mit der ersten Kugel aus Durchgang <n+1> ist - diesen Sonderfall kannst Du aber gezielt abfragen und in diesem Falle ausnahmsweise doch mal eine Kugel zurücklegen.

    Da Deine Aufgabenstellung jedoch im Web-Kontext dargestellt wurde, ist Dein Problem möglicherweise schwieriger. Wenn nämlich mehrere Anwender gleichzeitig Zitate aus Deinem Topf ziehen, kann es immer noch vorkommen, daß ein bestimmter Anwender nur einmal pro "Durchgang" an der Reihe ist und zufällig immer genau dasselbe Zitat angezeigt bekommt.
    In diesem Falle müßtest Du _pro_Anwender_ eine Urne aufstellen - sprich: Du müßtest Deine Besucher identifizieren können (Login, Session-ID, in erster Näherung wäre auch die IP-Adresse ausnahmsweise ganz brauchbar).

    Bedenke aber, daß die Verwaltung der Urnen dazu tendiert, ein Transaktionskonzept zu erfordern ... Du kannst eine wirklich schöne Lösung völlig ohne aufeinanderfolgende Duplikate bauen, wenn Du die richtigen Werkzeuge dafür einsetzt.
    Aber das Geheimnis dabei besteht darin, Deine Anforderungen _exakt_ zu beschreiben. Daß "zufällig" in Deinem Fall nicht ausreicht, sollte Dir inzwischen bewußt geworden sein.

    Es gibt übrigens eine triviale Methode, welche Deinem Besucher den Anschein des Zufalls bieten kann: Biete die Zitate einfach strikt sequentiell an! (Berechne die Position des nächsten Zitats aus der Position des vorherigen, die Du als CGI-Parameter zurück lieferst.)
    Falls Deine Zitate nach einer erkennbaren Methodik (alphabetisch etc.) sortiert sein sollten, kannst Du dies durch eine entsprechende Abbildung verschleiern.

    Beispiel für [1..10]: 6 - 9 - 2 - 5 - 8 - 1 - 4 - 7 - 10 - 3

    f(x) = (3x + 3) mod 10

    Wenn Du diese Position dem Besucher nicht explizit zeigst, dann sieht das für diesen schon ziemlich zufällig aus.

    Wenn Deine Zitatesammlung eher statischer Natur ist, dann kannst Du auch einmalig eine beliebige Permutation aller Zitate auswürfeln und die erwürfelte Position als zusätzliche Tabellenspalte abspeichern.
    Dann bekommt jeder Besucher Deine Zitate in einer für ihn undurchschaubaren, ursprünglich auch mal zufälligen, aber reproduzierbaren Reihenfolge zu sehen - und die Implementierung ist trivial (Du gibst "AND random_index = (N+1 mod Anzahl)" als zusätzliche Bedingung in der WHERE-Klausel an).

    Man muß nicht ständig würfeln, um dem Besucher etwas zu zeigen, das zufällig aussieht. Man muß nur wissen, was man eigentlich erreichen will ...

    Viele Grüße
          Michael

    --
    T'Pol: I apologize if I acted inappropriately.
    V'Lar: Not at all. In fact, your bluntness made me reconsider some of my positions. Much as it has now.