Zufälligen Datensatz selektieren
-
Sqwan schrieb:
Naja dein ausdruck liest ja eh die ganze spalte.
ORDER BY RAND() gibts doch auch garnicht.Viele DBS geben die Möglichkeit nach der Spaltennummer zu sortiern. Also
SELECT a,b,c FROM t ORDER BY 2
heißt dann nach b zu sortieren. Dadurch entsteht der zufällige Eindruck. Besser wäre sowas wie
SELECT * FROM t LIMIT 1 START RAND()
(Die genaue Syntax ist DBS-spezifisch). Wobei wohl der RND-Wert nicht größer als die Zeilenanzahl sein sollte.
@OP: Wenn Du Zeilen verdoppeln willst könntest du dich mit einem Kreuzprodukt versuchen. Nehmen wir mal an es gibt 10 Prioritäten:CREATE TABLE mult (v integer); INSERT INTO mult (1); INSERT INTO mult (2); INSERT INTO mult (3); INSERT INTO mult (4); INSERT INTO mult (5); INSERT INTO mult (6); INSERT INTO mult (7); INSERT INTO mult (8); INSERT INTO mult (9); INSERT INTO mult (10);
Deine Tabelle besitzt eine Spalte prioritaet. Dann vllt (ungetestet)
SELECT mytable.* FROM mytable,mult WHERE mult.v <= mytable.prioritaet
-
pseudocode:
float i = rand(); query = "select * from tabelle where priorität*"+i+">1 order by rand() limit 1";
mfg
xXx
-
ich denk ich würd eher subselects nehmen und dann via LIMIT eine zeile rausziehen
edit: sortieren kann da richtig langsam sein wenn kein index drauf ist und dieser müsste ja dann beim vorherigen beispiel auf alle spalten sein was totaler schrott ist
verwendets doch mal zum testen größere tabellen so ab 500mb dann klappts auch mit dem nachbarn
-
Hi,
neoexpert schrieb:
Hallo!
mitSELECT spalte FROM tabelle ORDER BY RAND()
kann ich einen zufälligen Datensatz auswählen.
Nun habe ich der Tabelle eine int-Spalte hinzugefügt. Da wird eine zahl abgespeichert. Mit dieser zahl möchte ich die wahrscheinlichkeit, dass ein datensatz ausgewählt wird erhöhen. Also je höher die zahl desto wahrscheinlicher.Um wieviel wahrscheinlicher ist es denn, dass eine eine Zeile mit prio = 3 gegenüber eine Zeile mit prio = 1 ausgewählt wird? Dreimal so wahrscheinlich? Und ggü. prio = 2 eineinhalb mal so wahrscheinlich?
Mir schwirren da zwei Ansätze im Kopf rum.
a) Du kannst IMHO über prio*RAND() sortieren
b) Der mathematische Ansatz:
Seien die Prioritäten p_1 bis p_n
Die Wahrscheinlichkeit, dass eine bestimmte Spalte i ausgewählt wird, ist also
p_i / (p_1 + ... + p_n) (diesen Ausdruck definiere ich mal als P_i. Er ist normalisiert ggü. allen Prioritäten)Eigentlich willst du nun eine Zufallszahl X ziehen, und dann schauen
Wenn 0 <= X < P_1, dann nimm Zeile 1
Wenn P_1 <= X < P_1+P_2, dann nimm Zeile 2
Wenn P_1 + P_2 <= X < P_2, dann nimm Zeile 2
...
Wenn Summe(P_j, j=1..i-1) <= X < Summe(P_j, j=1..i), dann nimm Zeile i
...
Wenn P_(n-1) <= X <= 1, dann nimm Zeile nDazu müsstest du dann allerdings eine Stored-Procedure (SP) schreiben, um das ordentlich zu lösen (die müsste, grob gesagt, die Zufallszahl (ZF) berechnen (vor deinem Statement, nicht in der SP, weil du ja nur eine ZF haben willst), und dann 1 zurückgeben, wenn die übergebene Zeile die ausgewählte Zeile ist, ansonsten 0. Ich befürchte, dass würde nicht ohne Subrequests funktionieren, da du in der SP tatsächlich alle Prioritäten brauchst).
Gruß, MJM
-
sauber löst man das nur mit einer ("denormalisierten" das eher das falsche wort) tabelle...
+-+
|a|
|a|
|b|
+-+und wieviel öfter zieh ich jetzt a statt b
-
ja genau so wollte ich das machen. Kann man irgendwie so eine Tabelle mit SQL basteln? In meiner int-spalte ist dabei die anzahl der gewünschten zeilen gespeichert.
-
deine int spalte bekommst dann mit nem group by... aber nein so einfach geht das nicht. entweder das script oder eine stored procedure kommt aber auch darauf an wennst häufig deine prioritäten änderst kannst das natürlich vergessen...
-
no_code schrieb:
+-+
|a|
|a|
|b|
+-+Geht das mit SQL aus einer tabelle
+-+-+
|a|2|
|b|1|
+-+-+
die Zeilen zu vervielfachen? Die zweite spalte ist dabei der Faktor um den vervielfacht wird.
+-+
|a|
|a|
|b|
+-+
-
kommt auf deine datenbank an. ohne stored procedures denke ich nein
-
statt die ganzen zeilen kannst auch ne 2. tabelle nehmen in der nur die ids für die erste tabelle liegen dann hast auch nicht nen ganz so großen overhead...
so wars gedacht...
+-+-+-+
|1|a|2|
|2|b|1|
+-+-+-++-+
|1|
|1|
|2|
+-+naja viel spaß beim frickeln