26. august 2005 - 11:50Der er
68 kommentarer og 1 løsning
Random alt det udtrukne
Jeg har et spørgsmål vedrørende udtræk af en Access Database.
Jeg har eg søgemaskine på min side, hvor man kan søge på handværkere.
Det jeg ikke finder ud af er, hvordan jeg kan vise disse udtræk i en tilfældig rækkefølge - således at den samme håndværker ikke vises øverst hver gang forespørgselen sendes.
jeg har kun set det brugt i mysql, så tænkte slet ikke på at man kunne i access, men det er klart, hvorfor skulle man ikke kunne det :o) Jeg må endnu engang se mig slået hehe
pallifo> De random-funktioner som er indbygget i diverse programmeringssprog og databaser er på ingen måde "tilfældige" - de simulere det bare rigtigt godt. Et seed - et frø - er en måde at starte en given random-generator der hvor man ønsker det.
pallifo >> asp eller ej, så er sådan noget random halløj lidt mere "universielt", et seed eller på dansk et frø, det er det man giver en random funktion at starte på. Det er jo sådan at i programmering er intet tilfældig, alt er planlagt, og derfor kan man ikke sige "giv mig et tal mellem 0-10" og regne med at få et tilfældig. Den funktion som regner det "tilfældig" ud skal have noget at starte på, nemlig et seed,
nielle >> men du kan vel ikke bare gøre som du skriver 14:48:23 for det svarer så til SELECT * FROM tabel ORDER BY 1 SELECT * FROM tabel ORDER BY 2 SELECT * FROM tabel ORDER BY 3 osv osv Den skal jo lave en order by rnd(id) altså et tilfældig id eller lignende
busschou> Du har muligvis ret, men jeg har desværre ingen måde at efterprøve det på lige i øjeblikket. Imidlertid er Rnd(id) jo allerede afprøvet og det gav alligevel den samme rækkefølge hver gang (26/08-2005 14:06:37).
Da jeg testede mit forslag, var det i Access med querybuilder og der fungerede det fint nok med skift i rækkefølgen. Det tilskriver jeg (efter at have fulgt med i denne tråd) det faktum at Access holder styr på "hvorlangt" man er kommet i rækkefølgen af tilfældige tal. Jeg ville tro at du på en eller anden måde skal sparke motoren igang med tilfældighedsgenerering hver gang, da konteksten som Access GUI har jo ikke eksisterer når man forespørger på den måde som du gør her...
nielle > Det var min oplevelse da jeg testede det i Access. Jeg tror det er fordi den samme værdi bliver brugt til at ordne efter. Det var derfor jeg forsøgte mig med ID'et for den aktuelle række...
SQL = "SELECT * FROM Handverkaralistin, Postnr, Bygd WHERE PostnummarID=PostnrID AND PostnummarID=BygdID AND Øki like '%"& District &"%' AND (Fyritøka like '%" & titel & "%' OR Lyklaorð like '%" & titel & "%') ORDER BY Rnd(HandverkaralistinId)"
Set RS = Conn.Execute()
count = 0
if RS.EOF then response.write "<b>Einki varð funnið!</b>" end if Do While Not RS.EOF
Jeg tror du skal bruge samme connection-objekt for at det skal have en chance for at fungere. Følgenden kode er tilrettet (under antagelse af at du allerede har en connection etableret i objektet conn):
<% Dim objCmd Set objCmd = Server.CreateObject("ADODB.Command")
SQL = "SELECT * FROM Handverkaralistin, Postnr, Bygd WHERE PostnummarID=PostnrID AND PostnummarID=BygdID AND Øki like '%"& District &"%' AND (Fyritøka like '%" & titel & "%' OR Lyklaorð like '%" & titel & "%') ORDER BY Rnd(HandverkaralistinId)"
ObjCmd.CommandText = SQL
Set RS = ObjCmd.Execute()
count = 0
if RS.EOF then response.write "<b>Einki varð funnið!</b>" end if
Det fungerer altså ikke for mig. Nu får jeg denne fejlmelding:
Microsoft OLE DB Provider for ODBC Drivers error '80040e37'
[Microsoft][ODBC Microsoft Access Driver] The Microsoft Jet database engine cannot find the input table or query 'Randomize'. Make sure it exists and that its name is spelled correctly.
SQL = "SELECT * FROM Handverkaralistin, Postnr, Bygd WHERE PostnummarID=PostnrID AND PostnummarID=BygdID AND Øki like '%"& District &"%' AND (Fyritøka like '%" & titel & "%' OR Lyklaorð like '%" & titel & "%') ORDER BY Rnd(HandverkaralistinId)"
ObjCmd.CommandText = SQL
Set RS = ObjCmd.Execute()
count = 0
if RS.EOF then response.write "<b>Einki varð funnið!</b>" end if
Hmm... Hvad nu hvis du kunne få en variabel værdi ind i dit SQL-statement, altså noget der aldrig var det samme, f.eks. en timer der kunne hjælpe med at give lidt varians i grundlaget for din tilfældighed...?
Så kunne det se således ud:
SELECT * FROM tabel ORDER BY Rnd(Rnd(ID) * Timer())
Jeg ved ikke helt hvor det kan være, men jeg kan komme i tanke om caching på
* klienten * på serveren * i connectionobjektet (lukker du connection hver gang?)
Jeg synes ikke selve der er nogen af de ovenstående eksempler der lyder sandsynlige, men man må jo skyde er det man kunne forestille sig var et problem... når nu man ikke har andet at gå efter :)
Hvad laver den timer, som vi satte ind i SQLsætningen tidligere?
Kan man måske uddybe den funktion lidt mere, og få timeren at starte fra forskellige steder for hver gang man sender en forespørgsel? Eller var det netop det, som timeren skulle gøre?
Timer skulle iflg. mine forventninger finde antallet af ticks siden kl. 12:00, så derfor forventede jeg at dem ville skifte mellem hver forspørgsel, hvilket burde være fint nok, da Rnd-funktionen så ville blive kørt med et nyt "seed" hver gang...
Det kan være du er nød til at sammensætte strengen med VBScripts Timer-funktion i stedet for at SQL-strengen ændrer sig imellem hver forspørgsel (man kunne forstille sig at der er connectionpooling som også kan have indvirkning på caching):
SQL = "SELECT * FROM tabel ORDER BY Rnd(Rnd(ID) * " & Timer & ")"
SQL = "SELECT * FROM tabel ORDER BY Rnd(ID) AND " & Timer & ""
Nogle gange får jeg en liste med en tilfældig rækkefølge (sådan som jeg ønsker at den skal fungere), mens jeg andre gange får denne fejlmelding:
1 - Microsoft OLE DB Provider for ODBC Drivers error '80004005' 2 - [Microsoft][ODBC Microsoft Access Driver] The Microsoft Jet database engine 3 - does not recognize '66' as a valid field name or expression. 4 - /leita1.asp, line 39
Tallet i linje 3 ('66') skifter dog i fejlmeldingen. Det hænger nok sammen med timeren, eller hvad???
Når du ændrede søgekriterierne virkede det alligevel lidt. Det giver mig et håb om at det kunne komme til at fungere med den metode jeg har lagt op til... Udfordringen bliver at finde ud af hvad det er der stimulerer en ny sekvens i tilfældighedsgeneratoren.
Hmmm, jeg opfatter egentlig bare "seed" som det tal der danner grundlag for tilfældighedsgeneratoren (Rnd-funktionen) og ikke som en max eller noget andet.
Du kan da prøve at udskifte
Timer
med
Timer MOD 200
så vil den bare tages resten af heltalsdivisionen og bruge som faktor for det som Rnd-funktionen returnerer (som i øvrigt er et decimaltal mellem 0 og 1).
Jeg kan ikke pt. komme på flere varianter til denne tilgang til problemet... jeg tror lige jeg skal hvile hovedet et par timer. Spekulerer lige over det...
Hvis det ikke virker, så prøv at kigge på din browsers indstillinger mht. hvor ofte den skal tjekke om der er sket ændringer til cachede sider. I internet explorer finder du disse indstillinger under:
Funktioner, Internetindstillinger..., fanebladet Generelt, gruppen Midlertidige internetfiler, knappen Indstillinger...
Hvis den ikke allerede står til det, så prøv at sætte den til at tjekke siden ved hvert besøg på siden.
Hvis du/vi er heldige, så klarer det problemet. I så fald kan du jo eksperimentere lidt med indstillingerne.
Hvis du bliver træt af at fedte rundt med SQL-udgaven (selvom jeg personligt ville foretrække den hvis det var min løsning :)), så kan du jo prøve denne udgave som er en konkretisering af busschou's forslag:
<%@ language="vbscript" codepage="1252" %> <% dim arrItems
function findNextItem(idx) findNextItem = Empty counter = 0 for num = 0 to ubound(arrItems,2) if idx > counter then if not isEmpty(arrItems(0,num)) then counter = counter + 1 end if else if not isEmpty(arrItems(0, num)) then findNextItem = arrItems(0, num) arrItems(0,num) = Empty exit for end if end if next end function
function showOutput() randomize maxItems = ubound(arrItems,2) for idx = 0 to maxItems rndIdx = CInt((maxItems - idx) * Rnd()) Response.Write(idx & " (" & rndIdx & "): " & findNextItem(rndIdx) & "<br>") next end function
dim strConn, objConn, objRs strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("database.mdb") set objConn = Server.CreateObject("ADODB.Connection") objConn.Open strConn set objRs = objConn.Execute("SELECT * FROM tabel") ' Omsæt recordset'et til et 2D-array hvor 1. dimension er ' kolonnenavnene og anden dimension er rækkerne ' Her er kolonnen "Navn" trukket ud, men flere kan trækkes ' ud ved at tilføje navnene i array'et ' (eksempel: objRs.getRows(-1,0,array("Navn","Adresse","Telefon"))) arrItems = objRs.getRows(-1,0,array("Navn")) objRs.close objConn.Close set objRs = nothing set objConn = nothing %> <html> <head> <title>Show databasecontent randomly ordered</title> </head> <body> <%=showOutput()%> </body> </html>
Ja, det er godt nok meget kode, når nu SQL'en med ORDER BY RND(ID) burde virke. Den virker i hvert fald hver gang hvis man kører forespørgslen direkte i Access. Jeg sætter mine penge på hesten ved navn "Cache".
Men du har da fået aftenen til at gå med lidt hyggelig kodemagi, ser det ud til. :-)
Jeg er som nævnt enig i at SQL udgaven ville være at foretrække og jeg oplevede som du selv at det i Access fungerede, derfor postede jeg mit forslag i starten af denne tråd. Jeg er dog blevet mere og mere i tvivl om hvorvidt det rent faktisk kan lade sige gøre med Rnd. Jeg har selv lavet et lille testprojekt, hvor jeg forsøger det samme, men det ser altså ud til at forspørgslen kommer igennem (den ændrer sig i det mindste hver gang, så siden bliver opdateret på serveren), men lige lidt hjælper det.
Jeg har søgt på google og fundet en udgave hvor man har en ekstrakolonne i tabellen, som opdateres med en tilfældig værdi inden udtrækket, men det er måske lige at gå over åen efter vand...
Ja, det ser jo ud til at virke! Tillykke! Virkelig flot arbejde. :))
Der er da ikke meget soft over dig, du er en rigtig hård nyser!
Jeg var ligesom dig kommet frem til, at der skete noget helt andet end i Access, når man bevægede sig over til ASP (nok fordi hele forbindelsen til databasen bliver lukket ned hver gang, så nummerserien starter fra samme sted hver gang). Modsat dig, var jeg endnu langt fra at have en løsning.
Nu må jeg hellere se at komme i seng, så jeg ikke falder i søvn på arbejdet i morgen (eller i dag er det jo)!
Jeg siger 1000-tak for jeres interesse. Eftersom dette er første gang, at jeg har startet en tråd, så må jeg lige finde ud af hvordan man uddeler point...
Jeg vælger at give softspot alle pointene, da han har lagt utrolig megen hjerne til denne tråd :o)
nielle >> Jeg synes selv det er spøjst at det skal gøres sådan for at det fungerer, men nogle gange (selvom jeg hader disse) erkender jeg bare at det kræver mere energi end jeg er villig til at investere, at forstå hvorfor tingene er som de er... uanset hvor ulogisk det er at det ene fungerer og det andet ikke gør.
Den virker i hvert fald i SQL Server - så måske virker den også i Access.
Synes godt om
Ny brugerNybegynder
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.