webForumDet fria alternativet

Slumpa olika poster

ASP

20 svar · 729 visningar · startad av bigsky

Medlem sedan maj 2002821 inlägg
Frågan#1

Sökte lite och hittade en del men ingen lösning som passade helt.

Jag vill slumpa fram tre olika poster's id från databasen för att sedan kunna skriva ut respektive fält för dessa. Det viktiga är att samma id får inte vara med i samma omgång så att säga.

Medlem sedan nov. 20017 144 inlägg
#2

Har du MySql kan du skriva så här:

SELECT * FROM tabl ORDER BY RAND() LIMIT 3
Medlem sedan maj 2002821 inlägg
#3

Nej tyvärr, det är Access som gäller.

Medlem sedan dec. 20003 887 inlägg
#4

Den som söker kan finna bara den orkar söka...

Det enda du behöver göra innan är att välja ut högsta och lägsta id:t från databasen och sedan slumpa fram tre unika id-nummer och göra en

SELECT hmm FROM tabell WHERE id IN ([i]de tre slumparna[/i])
Medlem sedan maj 2002821 inlägg
#5

Skulle man kunna få ett komplett exempel?

Medlem sedan jan. 20032 285 inlägg
#6

Typ såhär?

Dim arrID(0)
arrID(0) = "0"

intMax = objConn.Execute("SELECT Max(id) FROM [i]tabell[/i]")(0)

Do Until blnOK
  Randomize
  strSQL = "SELECT id FROM [i]tabell[/i] WHERE id = " & Int(Rnd() * intMax) + 1
  Set objRS = objConn.Execute(strSQL)

  If NOT objRS.EOF Then
    blnTemp = True

    For i = 0 To UBound(arrID)
      If CInt(arrID(i)) = objRS("id") Then blnTemp = False
    Next

    If blnTemp Then
      intCount = intCount + 1
      ReDim Preserve arrID(intCount)
      arrID(intCount) = objRS("id")
      strID = strID & objRS("id") & ","
    End If

    If intCount = 3 Then blnOK = True
  End If
Loop

strID = Left(strID, Len(strID) - 1)
strSQL = "SELECT * FROM [i]tabell[/i] WHERE id IN (" & strID & ")"
Set objRS = objConn.Execute(strSQL)

Fy vad jag är trött! Hoppas bara på att det inte finns fler än 20 fel i den där koden. ;)

/red 3 fel upptäckta och fixade. :p

Medlem sedan dec. 20003 887 inlägg
#7

Hrrm...

Private Sub RemoveFromArray(intValue, ByRef arrThis)
  Dim intIndex : intIndex = 0
  Dim blnFound : blnFound = False

  While Not blnFound
    intIndex = intIndex + 1
    If arrThis(i) = intValue Then blnFound = Not blnFound
  Wend

  For i = intIndex To UBound(arrThis)
    If Not i + 1 > UBound(arrThis) Then arrThis(i) = arrThis(i +1)
  Next

  ReDim Preserve arrThis(i - 1)
End Sub

Set objConn = Server.CreateObject("ADODB.Connection")
Set objRS = Server.CreateObject("ADODB.Recordset")

strSQL = "SELECT id FROM tabell"

objConn.Provider = "Microsoft.Jet.OleDb.4.0"
objConn.Open "Data Source=" & ...

objRS.Open strSQL, objConn, 1, 3

ReDim aintIDs(objRS.RecordCount + 1)
Dim i : i = 0

While Not objRS.EOF
  aintIDs(i) = objRS(0)

  objRS.MoveNext

  i = i + 1
Wend

objRS.Close
objConn.Close

Randomize

Dim aintRandom()
Dim intLeft : intLeft = 3
ReDim aintRandom(intLeft)

i = 0

While intLeft > 0 And UBond(aintIDs) > intLeft
  aintRandom(i) = aintIDs(Int(Rnd * UBound(aintIDs)))

  RemoveFromArray(aintRandom(i), aintIDs)

  i = i + 1
  intLeft = intLeft - 1
Wend

strSQL = "SELECT * FROM tabell WHERE id IN (" & Join(aintRandom, ",") & ")"
[blue]'Nu är det bara att välja ut posterna...[/blue]

Tro inte att den här koden fungerar rakt av för jag har skrivit den rätt upp och ner och skippat tester. Tänkte att du skulle få göra det ;)
Jag känner mig lite skeptisk till RemoveFromArray-funktionen, men det går att göra på andra sätt om man vill.

Du kan se det här som lågnivåpseudokod :)

Medlem sedan maj 2002821 inlägg
#8

Sebbe, den klagar på raden: ReDim Preserve arrID(intCount)

This array is fixed or temporarily locked

Medlem sedan dec. 20003 887 inlägg
#9

Prova utan Preserve.

Medlem sedan maj 2002821 inlägg
#10

No change.

Medlem sedan dec. 20003 887 inlägg
#11

Då är det väl dags att tänka om då :)

Dim aintIDs(), aintPosts()
strSQL = "SELECT id FROM tabell"

objRS.Open strSQL, objConn, 1, 3

ReDim aintIDs(objRS.RecordCount)

i = 0

[blue]'Fyll en array med alla befintliga id-nummer[/blue]
While Not objRS.EOF
  aintIDs(i) = objRS(0)
  i = i +1

  objRS.MoveNext
Wend

objRS.Close

i = 0
intLeft = 3
intIndex = 0

ReDim aintPosts(intLeft)

[blue]'Välj ut intLeft nummer ur "listan" (förutsatt att listan är större än intLeft)[/blue]
While intLeft > 0 And UBound(arrIDs) > intLeft
  [blue]'Slumpa ut ett index i arrayen[/blue]
  intIndex = Int(Rnd * (UBound(arrIDs) - i)

  [blue]'Lagra id-numret som fanns på den platsen...[/blue]
  aintPosts(i) = arrIDs(intIndex)

  [blue]'Ta bort det valda id-numret och stoppa dit ett som inte är använt.
  'Ful metod, som jag inte är säker på att den stämmer...[/blue]
  aintIDs(intIndex) = aintPosts(UBound(arrIDs) - i)

  i = i + 1
  intLeft = intLeft - 1
Wend

Response.Write Join(aintPosts, ", ")

Vi kan ju stanna där och se om det fungerar...

Medlem sedan maj 2002821 inlägg
#12

Ser ju ut att kunna funka, men hur skriver jag ut varje fält från databasen? Vart ska fältnamnen stå?

Medlem sedan dec. 20003 887 inlägg
#13

Forstättningen...

strSQL = "SELECT * FROM tabell WHERE id IN ("& Join(aintPosts, ",") & ")"

objRS.Open strSQL, objConn, 1, 3

For Each fldTemp In objRS.Fields
  Response.Write fldTemp.Name & vbTab
Next

Response.Write "<br>"

While Not objRS.Eof
  For Each fldTemp In objRS.Fields
    Response.Write fldTemp.Value & vbTab
  Next

  Response.Write "<br>"

  objRS.MoveNext
Wend

Ett sätt... förmodligen inte som du vill ha det dock.

Medlem sedan juni 200032 967 inlägg
#14

Om man vill kan man göra det lite enklare för sig, för man kan ju faktiskt slumpa direkt i SQL-frågan även med Access.

SELECT TOP 3 * FROM tabl ORDER BY RND(räknarfält)

Bör fungera i Access 97 och nyare.

Om man skulle vilja använda SQL Server kan man använda NewId() i sin ORDER BY istället.

mvh

Medlem sedan dec. 20003 887 inlägg
#15

Det verkar ju vara alldeles för enkelt :)
Betydligt smärtfriare att göra på det sättet dock.

Medlem sedan maj 2002821 inlägg
#16

Ja det hade ju varit suveränt. Men den slumpar ju inte alls. Det blir precis samma resultat som om man bara kör med TOP 3.

Medlem sedan nov. 20017 144 inlägg
#17

Kör du med RND() så måste du väl också sätta till "Randomize" före?:

RANDOMIZE
SELECT TOP 3 * FROM tabl ORDER BY RND(räknarfält)
Medlem sedan juni 200032 967 inlägg
#18

bigsky skrev:

Ja det hade ju varit suveränt. Men den slumpar ju inte alls. Det blir precis samma resultat som om man bara kör med TOP 3.

Konstigt. Jag fick jättefint resultat alla gånger jag testade. Vilken version av Access använder du?

Medlem sedan jan. 20032 285 inlägg
#19

bigsky skrev:

Sebbe, den klagar på raden: ReDim Preserve arrID(intCount)

This array is fixed or temporarily locked

Nu är jag väl kanske lite sent ute, men det ska nog funka om du ändrar raderna

Dim arrID(0)
arrID(0) = "0"

till

Dim arrID()
ReDim arrID(0)
arrID(0) = "0"
Medlem sedan maj 2002821 inlägg
#20

@nders skrev:

bigsky skrev:

Ja det hade ju varit suveränt. Men den slumpar ju inte alls. Det blir precis samma resultat som om man bara kör med TOP 3.

Konstigt. Jag fick jättefint resultat alla gånger jag testade. Vilken version av Access använder du?

Kör med MS Office Access 2003.

294 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
143 ms — deklarationer (db)
0 ms — hämta statistik (cache)
147 ms — hämta tråd, inlägg och bilagor (db)
139 ms — ändringar (db)