Avatar billede nil.dk Nybegynder
23. april 2001 - 23:44 Der er 25 kommentarer og
2 løsninger

Random Records

Jeg skal have skrevet 100 poster i en database ud i random rækkefølge.

Jeg har læst følgende artikel: http://www.4guysfromrolla.com/webtech/110800-1.3.shtml - men kan ikke få det til at virke... jeg vil gerne give flere points hvis der er en der hurtigt kan give mig en mere eller mindre færdig løsning.

Det haster.
Avatar billede nute Nybegynder
23. april 2001 - 23:48 #1
sånn henter du ut en tilfeldig post fra din tabell:

<%
strDSN = \"DRIVER={Microsoft Access Driver (*.mdb)};DBQ=\"&Server.MapPath(\"dindatabase.mdb\")
Set myConn = Server.CreateObject(\"ADODB.Connection\")
myConn.Open strDSN

Sql = \"Select count(*) as Found from [dintabell]\"
Set Record =  myConn.Execute(Sql)
Ialt = Record(\"found\")
Sql = \"Select * from [dintabell]\"
Set Record =  myconn.Execute(Sql)
Randomize
RandNum = Int(Rnd * Ialt) + 1
Record.MoveFirst
For i = 1 to RandNum - 1
    Record.MoveNext
next
response.write ...
myConn.Close
Set myConn = Nothing
%>

/nute
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:00 #2
Jeg skal ikke bruge EN tilfældig post, men alle posterne i tilfældig rækkefølge.
Avatar billede nute Nybegynder
24. april 2001 - 00:11 #3
hmm.....kan dette brukes ? det er ikke testet, bare skrevet raskt, men jeg håper du forstår prinsippet:

strDSN = \"DRIVER={Microsoft Access Driver (*.mdb)};DBQ=\"&Server.MapPath(\"[dindatabase]\")
Set myConn = Server.CreateObject(\"ADODB.Connection\")
myConn.Open strDSN
Dim chosenArr()
counter = 0
findNew = false

SQL = \"SELECT count(*) as found FROM [dintabell]\"
Set RS =  myConn.Execute(SQL)
total = RS(\"found\")
Redim chosenarr(total)
SQL = \"Select * from [dintabell]\"
Set Record =  myconn.Execute(Sql)
Randomize
while not RS.EOF
    rndNumber = Int(Rnd * total) + 1
    for i = 0 to counter
      if( chosenArr(i) == rndNumber AND NOT findNew) then
          findNew = true
        end if
    next
    if( NOT findNew ) then
        Record.Move(RandNum)
        response.write RS(\"[dinkolonne]\")
        ReDim preserve chosenArr( counter + 1 )
        chosenArr(counter) = RS(\"id\")
        findNew = false
    end if 
  RS.MoveNext
wend
myConn.Close
Set myConn = Nothing

/nute
Avatar billede perla Nybegynder
24. april 2001 - 00:17 #4
Har du databasen ?
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:18 #5
perla >> Hvad mener du?
Avatar billede perla Nybegynder
24. april 2001 - 00:20 #6
Så man kan teste om det virker, tabelnavn, feltnavne.
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:23 #7
Selvfølgelig har jeg databasen.

Navnene er ligegyldige.. dem kan jeg selv sætte ind bagefter.
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:35 #8
nute >> der er et eller andet galt.. den timer ud...
Avatar billede nute Nybegynder
24. april 2001 - 00:37 #9
hov....jeg ser jeg har benyttet Record som navn på et recordset istedenfor RS...replace alle Record med RS...
Avatar billede nute Nybegynder
24. april 2001 - 00:39 #10
hmmm.....det gikk tydeligvis litt hurtig dette her...prøv dette:

strDSN = \"DRIVER={Microsoft Access Driver (*.mdb)};DBQ=\"&Server.MapPath(\"[dindatabase]\")
Set myConn = Server.CreateObject(\"ADODB.Connection\")
myConn.Open strDSN
Dim chosenArr(), rndNumber
counter = 0
findNew = false

SQL = \"SELECT count(*) as found FROM [dintabell]\"
Set RS =  myConn.Execute(SQL)
total = RS(\"found\")
Redim chosenArr(total)
SQL = \"Select * from [dintabell]\"
Set RS =  myconn.Execute(Sql)
Randomize
while not RS.EOF
    rndNumber = Int(Rnd * total) + 1
    for i = 0 to counter
      if( chosenArr(i) == rndNumber AND NOT findNew) then
          findNew = true
        end if
    next
    if( NOT findNew ) then
        RS.Move(rndNumber)
        response.write RS(\"[dinkolonne]\")
        ReDim preserve chosenArr( counter + 1 )
        chosenArr(counter) = RS(\"id\")
        findNew = false
    end if 
  RS.MoveNext
wend
myConn.Close
Set myConn = Nothing

/nute
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:46 #11
der er stadig noget galt... den timer bare ud somom der er en uendelig løkke...
Avatar billede nute Nybegynder
24. april 2001 - 00:50 #12
hmmm....jeg ser ingenting galt bortsett fra at jeg har glemt å legge til

counter = counter + 1

helt til sist i

if( NOT findNew ) then
...
end if

men det skal ikke ha noe å si...

prøv å se om dette fungerer (bytt ut din while med denne):

while not RS.EOF
  rndNumber = Int(Rnd * total) + 1
  response.write rndNumber & \" \" & RS(\"[enkolonne]\") & \"<br>\"
  RS.MoveNext
wend

/nute
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:56 #13
YES! Nu virker det.

Tusind tak for hjælpen.
Avatar billede nute Nybegynder
24. april 2001 - 00:57 #14
anytime :)
Avatar billede nil.dk Nybegynder
24. april 2001 - 00:58 #15
Hov der var jeg lidt hurtig.. prøv at se her...

70 O
86 O
72 E
56 E
50 F
26 R
45 O
91 T
13 T
59 R
3 F
65 T
65 E
1 E
11 O
70 F
92 R
22 R
57 F
18 F
7 O
20 T
64 T
27 F
18 O
99 T
18 R
16 T
24 O
91 T
31 O
31 F
38 E
93 R
21 O
3 E
28 T
30 R
17 E
19 R
90 R
43 E
100 O
23 R
44 E
9 F
52 E
48 T
50 R
70 R
45 F
61 F
61 F
9 E
44 T
46 O
84 T
28 F
44 O
100 T
84 O
69 R
26 F
63 E
97 R
52 E
39 E
68 O
80 F
36 E
8 O
17 O
81 F
12 T
71 R
86 R
32 T
14 T
29 E
47 F
70 T
59 T
35 T
23 E
85 R
14 O
100 O
62 O
85 E
80 F
26 R
42 E
98 T
8 F
63 R
93 F
87 F
40 R
91 E
52 E


Der er jo gengangere...
Avatar billede nute Nybegynder
24. april 2001 - 01:09 #16
oki.....så skal du legge alle dine random nummer inn i en array....men uha...jeg merker at jeg begynner å bli trøtt og at jeg faktisk ikke klarer å overskue dette lenger :( har vært på arbeid siden klokken 0830 idag, så kreftene begynner å ta slutt...

prinsippet er at du legger alle dine random nummer inn i en array. For hver iterasjon av ditt recordset skal du sjekke om nummeret befinner seg i Arrayet. hvis det ikke gjør det, så skal du skrive ut det record som har tilsvarende id som random nummer.

dette skal fungere....prøv å debug litt med å ta vekk noe kode og se hvor du evt får en feil:

strDSN = \"DRIVER={Microsoft Access Driver (*.mdb)};DBQ=\"&Server.MapPath(\"[dindatabase]\")
Set myConn = Server.CreateObject(\"ADODB.Connection\")
myConn.Open strDSN
Dim chosenArr()
counter = 0
findNew = false

SQL = \"SELECT count(*) as found FROM [dintabell]\"
Set RS =  myConn.Execute(SQL)
total = RS(\"found\")
Redim chosenarr(total)
SQL = \"Select * from [dintabell]\"
Set Record =  myconn.Execute(Sql)
Randomize
while not RS.EOF
    rndNumber = Int(Rnd * ( total - counter ) ) + 1
    for i = 0 to counter
      if( chosenArr(i) == rndNumber AND NOT findNew) then
          findNew = true
        end if
    next
    if( NOT findNew ) then
        Record.Move(RandNum)
        response.write RS(\"[dinkolonne]\")
        ReDim preserve chosenArr( counter + 1 )
        chosenArr(counter) = RS(\"id\")
        findNew = false
        counter = counter + 1
    end if 
  RS.MoveNext
wend

/nute


Avatar billede nil.dk Nybegynder
24. april 2001 - 01:11 #17
Jeg tror også at jeg vil vende tilbage og kigge på det imorgen.. har også været på arbejde siden kl. 8.00
Avatar billede nute Nybegynder
24. april 2001 - 01:13 #18
:) god natt....
Avatar billede perla Nybegynder
24. april 2001 - 01:47 #19
Her er så eksesmplet omskrevet og testet (Kun med 1 felt, men da det oprindelige var n dimentionel kan det let omskrives.

<%
Function ReOrderArray2D(ByVal aArray)

  \'Get the upper and lower bounds from the second
  \'dimension (the row count)... also, create a temporary
  \'array, aTmpArray, to hold the reordered values
  Dim iCount, aTmpArray
  iCount = UBound(aArray, 2)
  ReDim aTmpArray(UBound(aArray, 1), UBound(aArray, 2))

  Dim iLoop, strIndex, iUpper, iLower
  iLower = LBound(aArray, 2)

  For iLoop = iLower to iCount
    strIndex = strIndex & CStr(iLoop)

    If iLoop < iCount then strIndex = strIndex & \",\"
  Next

  \'Choose a Random Index
  Randomize Timer

  Dim iRnd, aTmp, iTmpUpper, strNewIndex, iInnerLoop
  Redim aTmp(iCount)

  \'Loop through the array
  For iLoop = iLower to iCount
    iTmpUpper = iCount - iLoop

    \'Rebuild aTmp, the array of indexes
    ReDim Preserve aTmp(iTmpUpper)
    aTmp = split(strIndex, \",\")

    \'Add an element to the temp array...
    iRnd = Int(Rnd * (iTmpUpper + 1))
    For iInnerLoop = LBound(aArray,1) to UBound(aArray,1)
      aTmpArray(iInnerLoop, iLoop) = aArray(iInnerLoop, aTmp(iRnd))
    Next

    \'Compact aTmp, the array of indexes
    aTmp(iRnd) = aTmp(iTmpUpper)

    ReDim Preserve aTmp(iTmpUpper - 1)
    strIndex = join(aTmp, \",\")
  Next

  ReOrderArray2D = aTmpArray
End Function


\'Before we call ReOrderArray2D, we need to use the GetRows method to convert a Recordset into an array. This is quite simple, and can be seen with the following code:

\'Open up connection to database...
Set Conn = Server.CreateObject(\"ADODB.Connection\")
\'Conn.Open \"Driver={Microsoft Access Driver (*.mdb)};DBQ=\" & Server.MapPath(\"Support.mdb\")
strSQL = \"Select sagsnr from supportopgaver\"
set RS = Conn.execute( strSQL )

\'Create an Array variable and use GetRows
Dim aRows
aRows = RS.GetRows()

arows = ReOrderArray2D(aRows)

iCount = UBound(aRows, 2)
Dim iLoop, iLower
iLower = LBound(aRows, 2)

For iLoop = iLower to iCount
    Response.write aRows(0,iLoop) & \"<br>\"
Next

\'Clean up...
RS.Close
Set RS = Nothing

Conn.Close
Set Conn = Nothing
%>

-Per
Avatar billede nute Nybegynder
24. april 2001 - 10:44 #20
perla >> litt tungt og langt eksempel du kommer med.

denne burde faktisk kunne fungere:

SQL = \"SELECT count(*) as found FROM [dintabell]\"
Set RS =  myConn.Execute(SQL)
total = RS(\"found\")
chosenStr = \",\"
SQL = \"Select * from [dintabell]\"
Set Record =  myconn.Execute(Sql)

function randomNumber( num )
  Randomize
  tmpNum = Int(Rnd * num ) + 1
  if( inStr(chosenStr, \",\" & tmpNum ) > -1 ) then
    Call randomNumber( num )
  else
    chosenStr = chosenStr & tmpNum & \",\"
    total = total - 1
    randomNumber = tmpNum
  end if
end function


while not RS.EOF
  rndNumber = randomNumber(total)
  RS.Move(rndNMumber)
  response.write RS(\"[dinkolonne]\")
  RS.MoveNext
wend

/nute

Avatar billede perla Nybegynder
24. april 2001 - 10:50 #21
Ja, men det er det eksempel som han selv har henvist til, Og det hånterer ombytning af variabler i mere en en dimention. Dvs den er velegnet til recordset.

-Per
Avatar billede nil.dk Nybegynder
24. april 2001 - 11:05 #22
nute >>

dit script giver følgende fejl:

Out of stack space: \'randomNumber\'

perla >>

Dit virker, men hvordan skriver jeg flere felter ud på samme tid?
Avatar billede perla Nybegynder
24. april 2001 - 11:09 #23
Hvis du select 2 felter i din SQL, vil den første parameter i ARows være feltet, Dvs at ved 3 felter vil du skulle bruge 0,1,2 som værdier.

Response.write aRows(0,iLoop) & \"<br>\"

-Per
Avatar billede nute Nybegynder
24. april 2001 - 11:09 #24
sant nok, men det er egentlig ikke noe poeng å bytte om rekkefølgen i Recordset\'et...man skal jo bare skrive ut det tilfeldig rekkefølge...

en annen faktisk simplere måte er jo å benytte RAND funksjonen i SQL, men den har jeg ikke arbeidet med. Poenget med den er at man kan, i sin SQL, opprette en pseudo kolonne med tilfeldige tall som man deretter sorterer etter...skal se om jeg ikke kan få det til å fungere :)

/nute
Avatar billede nute Nybegynder
24. april 2001 - 11:11 #25
du skal bare skrive ut alle feltene du vil skrive ut...på vanlig måte:

response.write RS(\"en\") & \" \"  & RS(\"to\") \'og så videre...

/nute
Avatar billede nil.dk Nybegynder
24. april 2001 - 11:17 #26
Jeg bliver nødt til at lukke nu.. skal videre med opgaven.

Jeg bruger perlas eksempel, da det bygger på mit oprindelige script og da det er det første jeg kunne få til at virker.

Jeg giver jer dog begge point, for nute har også lavet et stort stykke arbejde.

Tak begge to..
Avatar billede nute Nybegynder
24. april 2001 - 11:18 #27
selv takk....
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester