Jag ska välja 4 stycken poster ur db slumpmässigt. Detta får jag att fungera bra , men hur gör man om man vill undvika att samma post visas två gånger? För det är väl troligt att samma post kan slumpas fram flera gånger? har du nån kod att visa? eller kom på att det nog inte är så bra ide... Hur slumpar du nu? Du kan ju använda TOP/LIMIT för att plocka ut alla fyra posterna samtidigt, då kommer du inte få samma post flera gånger. Här kommer koden jag använder nu....... Hej Så jag kan altså slumpa fram posterna direkt i SQL-satsen? Hej OK, till att börja med så antar jag att det är MySQL vi pratar om här eftersom LIMIT inte finns i så många andra produkter. Dock används nyckelordet TOP i något inlägg högre upp, så jag undrar om det verkligen är MySQL frågan här gäller? Hej Jag använder en access DB. En lösning som funkar på alla "dbms":Välja ut poster ur db med Randomize
Sv: Välja ut poster ur db med Randomize
testa sätt till
group by id
i din SQLSv: Välja ut poster ur db med Randomize
tror det finns nått som heter distinct som du kan användaSv: Välja ut poster ur db med Randomize
/JohanSv: Välja ut poster ur db med Randomize
//Först räknar jag antalet poster i mitt recordset:
<%
antal_poster = 0
do until RS.EOF
antal_poster = antal_poster + 1
RS.Movenext
Loop
RS.Movefirst
//Så här ser själva koden ut för att välja ut 4 stycken poster slumpmässigt:
for n = 1 to 4
randomize
post = Int((RND * antal_poster) + 1)
RS.Movefirst
RS.Move post
%>
<td>Här skrivs varje post ut</td>
<%next%>Sv: Välja ut poster ur db med Randomize
order by rand() limit XX ger slumpmässigt resultat, dvs du kan få dubletter.
Jag rekommenderar dig att använda rand() limit 1 och loopa tills önskat antal
returnerats. Vid varje loop kolla, mot en resultat array, att resultatet är unikt, är det inte det skippa o loopa igen.
Mvh
JohanSv: Välja ut poster ur db med Randomize
då kan jag väl skriva :
select TOP 4 from tabell where ...... order by rand() ??Sv: Välja ut poster ur db med Randomize
randomize
select * from tabell order by rand() limit 10
ger 10 slumpmässiga rader men det kan vara dubletter i denna resultattabell.
det är därför du måste, som jag ser det, begränsa din slumpmässiga utsortering till 1, limit 1, och sedan kontrollera resultatet mot en array som du skapar..
undrar hur det skulle bli med
select distinct(*) from tabell order by rand() limit 20? Antaligen skulle du inte få en resultatabell med 20 då... eftersom distinct sorterar bort dessa.. inge bra det heller men kanske värt att testa.
Mvh
JohanSv: Välja ut poster ur db med Randomize
Sedan så undrar jag om det du skriver verkligen stämmer, vilket isf innebär att det är MySQL som återigen beter sig mycket konstigt.
> randomize
> select * from tabell order by rand() limit 10
> ger 10 slumpmässiga rader men det kan vara dubletter i denna resultattabell.
Eftersom SQL är ett mängdbaserat språk ska egentligen alla rader få samma värde från rand()-funktionen (eftersom den ska endast köras en gång för hela mängden), men förmodligen är den funktionen speciellt kodad till att inte göra det utan istället köras en gång för varje rad. Funktionen newid() i SQL Server (skapar en ny UUID (GUID)) fungerar likadant, den körs alltid en gång för varje rad. Därför kan man i SQL Server skriva SELECT TOP 10 * FROM FOOBAR ORDER BY NEWID() och få en slumpmässig sortering. Observera dock att det innebär att newid() måste köras en gång för varje rad i tabellen, och har man en stor tabell så kan det ta mycket tid och resurser.
Varför kan det bli dubletter i ditt exempel? Varje rad får ett värde från rand() (även om alla raderna får samma värde gör det ingen skillnad), och därefter returneras de 10 rader som fick de lägsta värdena. Det ska aldrig kunna göra att vissa rader returneras flera gånger?!
> select distinct(*) from tabell order by rand() limit 20? Antaligen skulle du inte få en resultatabell med 20 då... eftersom distinct sorterar bort dessa.. inge bra det heller men kanske värt att testa.
DISTINCT plockar bort dubletter i resultatet, men det måste väl ändå ske innan sortering? Alltså bör man fortfarande få 20 rader, i slumpmässig ordning (om inte rand() ger samma värde för alla rader).Sv: Välja ut poster ur db med Randomize
jag har testat lite grann, resultattabellen blir det angivna antalet och det ser inte ut som det blir dubletter.
Bra funktion.
Men, det kanske är MySQL unikt så det kanske inte hjälper frågeställaren som jag uttryckte mig men det kanske går att omformulera frågan så den passar andra miljöer.
Med vänlig hälsning
JohanSv: Välja ut poster ur db med Randomize
Då kan man inte använda rand() ?Sv: Välja ut poster ur db med Randomize
<%
Option Explicit
Dim objConn
Dim strSQLrnd
Dim rstRnd
Dim varyRecs
Dim varyRnd
Dim N
'## -- 3 fält namngivna i sql-frågan kommer att ge 3 positioner i arrayen
'## eftersom vi kommer att hämta vår data med .GetRows och få en
'## 2-dimensionell array tillbaka
strSQLrnd = "SELECT Field1, Field2, Field3 FROM MyTable"
Set objConn = Server.CreateObject("ADODB.Connection")
objConn.Open "MyConnString"
Set rstRnd = objConn.Execute(strSQLrnd)
If Not rstRnd.EOF Then
'## -- fetch array --
varyRecs = rstRnd.GetRows(-1)
End If
Set rstRnd = Nothing
objConn.Close
Set objConn = Nothing
'## -- random posts from array --
'## varyRecs som argument för arrayen
'## 5 för antal "poster" som vi vill ha slumpat
'## 3 för antal positioner för varje index i arrayen (3 fält i sql-frågan)
varyRnd = Random(varyRecs, 5,3)
'## -- kontrollera att vi fått tillbaka några poster
If IsArray(varyRnd) Then
For N = 0 TO UBound(varyRnd,2)
Response.Write "ID: " & varyRnd(0,N) & " Data: " & varyRnd(1,N) & "<br>"
Next ' N
End If
'## -- get iRnd random values from array --
'## argument: vArray a 2-dimensional array
'## argument: iRnd how many random posts we need
'## argument: intPost how many posts for each index in the 2-dimensional array
Public Function Random(ByVal vArray, ByVal iRnd, intPos)
If Not IsArray(vArray) Then Exit Function
If Not IsNumeric(iRnd) OR Not IsNumeric(intPos) Then Exit Function
Randomize
Dim varArray
Dim intMaxIndex
Dim intRandomIndex
Dim N
Dim X
intPos = intPos - 1
'## -- how many indexes in the array --
intMaxIndex = UBound(vArray,2)
'## -- kontrollera så att vi inte väljer att få ut fler
'## slumpade poster än det finns poster (index) i arrayen --
If iRnd > intMaxIndex Then iRnd = intMaxIndex
ReDim varArray(intPos, iRnd - 1)
'## -- get iRnd random values from array --
For N = 0 To iRnd - 1
'## -- get random index values from "mother" array --
intRandomIndex = CInt(rnd * (intMaxIndex - N))
'## -- save random data --
For X = 0 TO intPos
varArray(X, N) = vArray(X,intRandomIndex)
vArray(X, intRandomIndex) = vArray(X,intMaxIndex - N)
Next
Next
'## -- return an array of iRnd random selected from "mother" array --
Random = varArray
End Function
%>
Lite jobbig blir den när det finns många poster i db ..... 1000 eller fler ;o)
redigerat:
OBS! kanske inte buggfri då jag klippte ut koden. Ingår i en del av mina komponenter, fast då med random för vanliga arrayer oxå.
/redigerat
cya,
PatrikB