Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:29 Der er 46 kommentarer og
1 løsning

random, men ikke den samme 2 gange i streg

Jeg har lavet denne function som skulle trække en ramdom citat ud af en database hver gang funktion bliver brugt, men jeg kan ikke få den til at virke ordenlig :(

function randomcitat() {
$foresp = mysql_query("SELECT * FROM mamster_citat WHERE id != '$_SESSION[lastcitat]' ORDER BY rand() LIMIT 0,1") or die(mysql_error());
    while($row = mysql_fetch_array($foresp)) {
        $id     = $row["id"];
        $citat     = $row["citat"];
       
        echo"$citat";
       
        $lastcitat = $id;
       
        session_register("lastcitat");
    }
}

Jeg har sat en session således at man kan kontrollere at det samme citat ikke bliver vist 2 gange i streg!

I kan se functionen i funktion på www.myserver.lir.dk/mamster.dk øverst under MAMSTER-logoet!

Der kan I også se fejlen! (den viser næsten den samme hver gang, man skal reloade siden midst 20 gange en der kommer en ny... :/)

Håber der er en klog ekspert som altid der kan hjælpe mig med at få lavet min function så den virker :)
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:33 #1
Jeg har en gammel idé på dette område (jeg kan ikke huske om du har set
den - du har da vist spurgt om det før):

Tæl hvor mange gange hvert citat er vist, vælg det citat (et af de
citater) der har været vist færrest gange, og tæl antallet op.
Det er ikke random for den enkelte, men er der blot lidt besøg på
siden, så virker det fint.

Ellers er det vist noget med en ændret rand() funktion i MySql i de
nyere versioner.
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:40 #2
Indtil nu regner jeg ikke med særlig mange besøgende ;)

Vil det sige du i tabellen vil have jeg tilføjer en kolonne, fx hits som bliver opdateret hver gang den bliver vist?

Hvordan vil du så lave koden til at vælge den med midst, fx hvis der er flere som har samme hits antal?

(og kan godt være jeg har haft oprettet ligende spørgsmål engang, men har ikke fået denne "gamle idé" af dig før ;))
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:42 #3
noget ligende dette?

    function randomcitat() {
        $foresp = mysql_query("SELECT * FROM mamster_citat ORDER BY hits DESC LIMIT 0,1") or die(mysql_error());
            while($row = mysql_fetch_array($foresp)) {
            $id     = $row["id"];
            $citat     = $row["citat"];
               
            echo"$citat";
           
            mysql_query("UPDATE mamster_citat SET hits = hits+1 WHERE id = '$id'") or die(mysql_error());
        }
    }
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:43 #4
select * from citater order by count asc limit 1

vælger én af de mindste, og hvis $id er den valgte så

update citater set count=count+1 where id=$id
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:43 #5
ok, du var hurtigere... men ASC, ikke DESC
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:44 #6
Det skulle lige sorteres efter ASC i stedet for DESC ellers virkede det :D

- du er sgu genial knægt :)  læg et svar!!
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:44 #7
hvad er det det ASC gør så det virker istedet for DESC, ved godt det er hvilken vej, men hvorfor viser den ikke noget med DESC?
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:45 #8
Og så ved oprettelse af nye skal du sætte count lig med den
mindste af de eksisterende. Som du kan forstå er det mere en
idé - jeg har aldrig haft brug for at prøve.
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:45 #9
Med DESC får du den største, som du så tæller op. Så bilver den
altid vist.
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:47 #10
sårn set ligegyldigt om det er en idé eller noget du har arbejdet på i flere år! bare det virker, hehe :D

er der en nem måde jeg kan hive det laveste hitstal ud med?

- læg et svar!!
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:49 #11
select min(count) as mindste from citater.

Suk - længe, meget længe siden nogen har kaldt mig for knægt....
Avatar billede elskermad.dk Nybegynder
20. maj 2003 - 22:52 #12
:D
er det så godt eller skidt?? hehe

Jeg siger i hvert fald mange tak for hjælpen (knægt *GG*) :D
Avatar billede nielle Nybegynder
20. maj 2003 - 22:54 #13
Problemet med den beskrevne algoritme er blot at: Hvis citaterne har været vist sån' cirka 100 gange hver, og du så lægger et ny citat i databasen, så vil dette blive vist hver eneste gang de næste 100 gange.

Det var da vist ikke det du ville have?
Avatar billede erikjacobsen Ekspert
20. maj 2003 - 22:56 #14
Det er løst: 20/05-2003 22:49:00 og før
Avatar billede nielle Nybegynder
20. maj 2003 - 22:59 #15
Nu er jeg slet ikke inde i PHP så her kommer noget pseudo kode:

Max_ID = Resultat af "SELECT count(*) FROM Citater"
Nyt_ID = Gammelt_ID

do while Nyt_ID=Gammelt_ID
  Nyt_ID = random(Max_ID)
loop

Citat = SELECT * FROM Citater WHERE ID=Nyt_ID
Avatar billede tipsen Nybegynder
21. maj 2003 - 00:12 #16
Du kan også bare prøve at seede RAND-funktionen som det anbefales i nyere versioner af MySQL:

SELECT * FROM mamster_citat WHERE id != '$_SESSION[lastcitat]' ORDER BY RAND(NOW()) LIMIT 0,1
Avatar billede nielle Nybegynder
21. maj 2003 - 07:44 #17
tipsen-> Men pointen er jo netop at elskermad.dk ikke vil have det samme citat 2 gange lige efter hinanden. Det er det min while løkke løser.
Avatar billede tipsen Nybegynder
21. maj 2003 - 08:59 #18
nielle: elskermad.dk ønsker at trække et tilfældigt citat ud af db'en og har problemer med at den kan vise post 1 20 gange i træk, hvilket jo næppe er særligt tilfældigt! Årsagen til dette er, ifølge MySQL.com, at RAND() funktionen skal seedes i nyere versioner af MySQL, hvorfor den her fodres med med NOW() som seed, hvilket giver "mere tilfældige" citater og problemet er løst.
Avatar billede nielle Nybegynder
21. maj 2003 - 09:16 #19
tipsen-> Problemet er *ikke* løst, hvis ikke man husker hvad det forrige citat var og så prøver igen hvis man tilfældigvis trækker det samme (uanset at man måtte bruge en "mere tilfældig" random funktion).

Forresten skal min pseudokode lige justeres sådan at man husker det nye citat:

Max_ID = Resultat af "SELECT count(*) FROM Citater"
Nyt_ID = Gammelt_ID

do while Nyt_ID=Gammelt_ID
  Nyt_ID = random(Max_ID)
loop

Gammelt_ID = Nyt_ID

Citat = SELECT * FROM Citater WHERE ID=Nyt_ID
Avatar billede tipsen Nybegynder
21. maj 2003 - 10:02 #20
nielle: Hvorfra stammer dit påståede problem - det fremgår ikke af spørgsmålet så vidt jeg kan se!?

Det jeg mener at kunne se er at elskermad.dk ikke er tilfreds med at MySQL "tilfældigt" udvælger citat 1 adskillige gange i træk, hvilket skyldes den måde RAND() funktionen fungerer på efter v. 3.23.54 af MySQL. Dette problem er løst i den SQL-query jeg har skrevet ovenfor i en kommentar.
Avatar billede nielle Nybegynder
21. maj 2003 - 10:12 #21
tipsen-> Overskriften på spørtgsmålet var da vist "random, men ikke den samme 2 gange i streg". Derfor!

Det kommer selvfølgeligt an på hvor religøs man er med om det samme citat *ikke* må komme to gange i træk. Selv ville jeg synes at det var lidt kikset (men selvfølgeligt mindre kikset end hvis det kom 20 gange i træk!); Faktisk ville jeg kalde det for sløset programering.
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 10:14 #22
brug af rand() har det gammelkendte problem, at det er langsomt, og tager
tid proportionalt med længden af tabellen. Det gør min "metode" også, med
mindre man husker at gøre tællefeltet indexeret. Det er så ikke lige afprøvet,
men skulle gøre det muligt at få konstant tid opdatering og aflæsning.
Avatar billede tipsen Nybegynder
21. maj 2003 - 10:29 #23
nielle: Jeg havde ikke læst overskriften - så ok! Jeg mener så det er begrænset, hvor meget tid man skal bruge på at løse sådan et problem - og også hvor lang server-tid funktionaliteten må bruge hver gang en side requestes - det er i mine øjne irrelevant om et citat vises to gange i træk - sålænge det stadig er tilfældigt!

Erik: Det med lineær kompleksitet havde jeg ikke overvejet, men det er selvfølgelig rigtigt...
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 10:34 #24
...og hvis der oveni er det krav at der ikke må komme samme citat to gange i
træk, så husk det første citat i en sessionvariabel, træk ikke et men to
citater ud (med lavest tæller), og hvis det første er det samme som i
den sessionvariabel, så tager man den anden.

Jeg må se at få det testet en dag ... !!

Nellie: du udnytter i dit script, at der ikke er huller i ID-erne, og det
kan der sagtens være når man begynder at slette citater. Derfor dur det ikke.
Avatar billede tipsen Nybegynder
21. maj 2003 - 11:17 #25
En ny funktion der i stedet benytter php's rand-funktion:

function randomcitat() {
  $res = mysql_query("SELECT COUNT(*) FROM mamster_citat WHERE id <> '$_SESSION[lastcitat]'") or die(mysql_error());
  $antal = mysql_result($res,0);
  mysql_free_result($res);
  if ($antal > 0) {
    $rndnum = mt_rand(0, $antal-1);
    $res = mysql_query("SELECT id, citat FROM mamster_citat WHERE id != '$_SESSION[lastcitat]' LIMIT $rndnum, 1") or die(mysql_error());
    list($id, $citat) = mysql_fetch_row($res);
  }
}

Der er så mulighed for at få 2 identiske citater i træk, men hvis man slår med terninger, kan man jo også få 2 seksere i træk!

Erik: Kan du umiddelbart se nogle problemer med denne metode? (Nu er tiden konstant - jeg ved så bare ikke om den er for langsom...)
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 13:24 #26
Så snart du har en where på har mysql svært ved at finde din limit xxx,1
fordi den skal "alt" igennem. Drop where betingelsen og skriv limit xxx,2 og
lav testet derefter. JEg er ikke helt på det rene med hvilke optimeringer
der kan eller ikke kan udføres, men på denne måde burde mysql være en lille
smule hurtigere.
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 19:07 #27
uh ha, kan se at I er lidt uenige om hvordan det skal laves, og jeg er ikke nok inde i mysql til at kunne gennemskue hvilken måde jeg skal vælge for at få den hurtigste metode (hvis et citat kommer 2 gange i streg en enkel gang imellem sker der ikke noget ved det!)
Avatar billede tipsen Nybegynder
21. maj 2003 - 19:16 #28
Erik: Det var vist også en hjerneblødning fra min side - det var meningen at det skulle være en "ren" løsning - dvs. uden det pjat med at huske sidste citat! Dvs. følgende var hvad jeg mente:

function RandomQuote() {
  $res = mysql_query('SELECT COUNT(*) FROM mamster_citat') or die(mysql_error());
  $antal = mysql_result($res,0);
  mysql_free_result($res);
  if ($antal > 0) {
    $rndnum = mt_rand(0, $antal-1);
    $res = mysql_query('SELECT citat FROM mamster_citat LIMIT $rndnum, 1') or die(mysql_error());
    return mysql_result($res, 0);
  } else {
    return 'Intet citat fundet!';
  }
}

echo RandomQuote();
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 19:21 #29
tipsen, kan du lave functionen således at den udskriver det uden at man skal bruge echo?
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 19:27 #30
functionen virker ikke! :/

fejl i $res = mysql_query('SELECT citat FROM mamster_citat LIMIT $rndnum, 1') or die(mysql_error());
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 19:34 #31
Jeg bruger dette nu:

    function randomcitat() {
        $foresp = mysql_query("SELECT * FROM mamster_citat ORDER BY hits ASC, RAND(now()) LIMIT 0,1") or die(mysql_error());
            while($row = mysql_fetch_array($foresp)) {
            $id    = $row["id"];
            $citat  = $row["citat"];
               
            echo"$citat";
           
            mysql_query("UPDATE mamster_citat SET hits = hits+1 WHERE id = '$id'") or die(mysql_error());
        }
    }

Hvis det er meget dårligt mht loadtiden må I meget gerne lige lægge en kommentar
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 19:40 #32
Bruger du både hits og RAND(now()) ?
Avatar billede tipsen Nybegynder
21. maj 2003 - 19:42 #33
function RandomQuote() {
  $res = mysql_query('SELECT COUNT(*) FROM mamster_citat') or die(mysql_error());
  $antal = mysql_result($res,0);
  mysql_free_result($res);
  if ($antal > 0) {
    $rndnum = mt_rand(0, $antal-1);
    $res = mysql_query("SELECT citat FROM mamster_citat LIMIT $rndnum, 1") or die(mysql_error());
    echo mysql_result($res, 0);
  } else {
    echo 'Intet citat fundet!';
  }
}

RandomQuote();
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 19:42 #34
ja, for når jeg ikke har særlig mange besøgende på min side, vil den besøgende jo hurtigt se den kommer i samme rækkefølge?? Er det da ikke smart?
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 19:45 #35
Se at få dig nogle flere citater.

"Der er tre slags mennesker. Dem der kan tælle, og dem der ikke kan."
Avatar billede tipsen Nybegynder
21. maj 2003 - 19:57 #36
Kan da også lige et par stykker :-)

I could prove God statistically.
          George Gallup
The last good thing written in C++ was the Pachebel Canon.
          Jerry Olson
Problems cannot be solved at the same level of awareness that created them.
          Albert Einstein (1879-1955)
Multimedia? As far as I'm concerned, it's reading with the radio on!
          Rory Bremner
Avatar billede erikjacobsen Ekspert
21. maj 2003 - 20:00 #37
"Der er to slags mennesker. Dem der deler folk op i to grupper, og
dem der ikke gør"
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 20:01 #38
hehe, tror sgu ikk at dem der kommer på min side kan tælle, har haft samme regnelærer som mig ;D (siger det hele, hehe)

og self skal jeg have noen flere citater, men skal jo li falde over dem lidt efter lidt!

ehmn tipsen, hvis du kigger på siden, så kan du se hvordan "mine" "citater" er... ikke helt de samme *GG*
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 20:03 #39
ehmn skal jeg ikke oprette et nyt spm med noen points til jer? For i har jo brugt en del tid på at gøre "mit" script bedre!?
Avatar billede tipsen Nybegynder
21. maj 2003 - 20:29 #40
damn den tager lang tid at hente på min 2.5mbit forbindelse... :-/
Avatar billede elskermad.dk Nybegynder
21. maj 2003 - 23:47 #41
er det bare gfx eller er det selve siden der er bygget forkert op?
Avatar billede tipsen Nybegynder
22. maj 2003 - 00:37 #42
skal ikke kunne sige det, men der var vist en del grafik?
Avatar billede elskermad.dk Nybegynder
22. maj 2003 - 18:10 #43
jah der er lidt, men hvis det er grafik, så er det vel kun førte gang man kommer på siden at det tager "ekstra" lang tid om at hente det?
Avatar billede tipsen Nybegynder
22. maj 2003 - 21:36 #44
Det er kun første gang det tager *rigtig* lang tid >10 sek. hvilket er *for* lang tid for mig...

Det tog 16sek at hente ca. 100k og det er vist ikke min forbindelse der er flaskehalsen - min pointe er bare, at det er for længe og for meget data - specielt baggrunden tilter...

Har lige testet med baggrunden og pga. dens udseende kan du gemme den i meget lav kvalitet uden at se kvalitetstab - det er fra 61kb -> 10kb!
Avatar billede elskermad.dk Nybegynder
22. maj 2003 - 22:11 #45
nu har jeg ændret baggrundsbilledet til ca 11kb gør det det bedre?
Avatar billede tipsen Nybegynder
23. maj 2003 - 00:16 #46
Kan ikke finde serveren.
Avatar billede elskermad.dk Nybegynder
24. maj 2003 - 18:09 #47
det kan du nu igen, det er pga den kører lokalt på min egen computer, og den har været slukket nogle timer!!
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
Vi tilbyder markedets bedste kurser inden for webudvikling

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