Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP] Losowe wyświetlanie pytań.
Forum PHP.pl > Forum > Przedszkole
blade-mrn
Witam,
Mam w bazie danych w jednej tabeli zapisane pytania i w drugiej przypisane im odpowiedzi. Pytania są wyświetlane na stronie pojedynczo za pomocą stronicowania.
Chciałbym aby te pytania za każdym razem wyświetlane były w innej kolejności (bez powtórzeń) tyle że nie wiem jak można taki efekt uzyskać. Ma ktoś jakąś radę??
Diabl0
ORDER BY RAND()

http://dev.mysql.com/doc/refman/5.0/en/mat...l#function_rand
blade-mrn
Wszystko fajnie bo ORDER BY RAND() działa tyle że pytania się powtarzają.
wonski
Musisz sobie zapisywać (np. sesja lub $_GET), które pytania zostały już wykorzystane i wykluczać je z kolejnego zapytania.
Diabl0
1 - jeśli pytań w teście jest określona liczba (np. 20) - to pobrać cały zestaw pytań od razu i trzymać w sesji
2 - Pytań może być dowolna liczba - zapisywać użyte pytania w sesji i i przy losowaniu nowego pytania odrzucać już użyte pytania albo w samym select (WHERE id NOT IN (1,3) ) albo rekurencyjnie w PHP dopóki nie wylosujesz pytania jeszcze nie używanego. Wybór metody zależy od stosunku pzeciętnej ilości pytań wyświetlanej na usera do ogólnej liczby wszystkich dostępnych pytań i po prostu trzeba sobie samemu sprawdzić co będzie wydajniejsze.
3 - jeśli wyniki odpowiedzi zapisujesz na bazie można napisać select losujący pytanie na które user jeszcze nie ma zapisanej odpowiedzi (select zależny od kontrukcji tabel)

qrzysztof
Pobrać do tablicy (trzymać w sesji). Tablicę RAZ zrandomizować. A potem zwykłym array_pop.

Funkcja mieszająca tablicę:

  1. public static function randomizeArray ($inArray) #miesza tablice przekazana w argumencie (te same elementy ale w losowej kolejnosci)
  2. {
  3. $tempArray=array();
  4. $inArrayLength=count($inArray);
  5. for ( $i=0; $i < $inArrayLength; $i++ )
  6. {
  7. $rnd=rand();
  8. $tempArray[$i]=$rnd;
  9. }
  10.  
  11. asort($tempArray); #sortuje tablice alfabetycznie (z zachowaniem kluczy)
  12. $randomizedArray=array();
  13.  
  14. $tempKeys=array_keys($tempArray); #zwraca klucze tablicy
  15. foreach( $tempKeys as $key )
  16. {
  17. $randomizedArray[]=$inArray[$key];
  18. }
  19.  
  20. return $randomizedArray;
  21. }
marcio
A zwykly select distinct() z order by rand() nie wystarczy?
thek
Skoro już jesteśmy przy temacie tablic... To może użyć array_pop() ? To nam automatycznie usunie to pytanie z tablicy smile.gif A to czy my w niej będziemy trzymać całe pytania czy tylko ich numery... A kogo to obchodzi? tongue.gif
qrzysztof
Cytat(marcio @ 7.11.2009, 19:58:38 ) *
A zwykly select distinct() z order by rand() nie wystarczy?


Może wystarczyć.

Trochę mało danych mamy. Autor mógłby napisać coś więcej w jaki sposób chce pobierać te dane z bazy. Ile tych pytań. Wszystkie na raz, jakiś podzbiór czy po jednym z całości.

Czy przypadkiem randomizacja na poziomie php nie jest efektywniejsza? "Order by Rand()" cieszy się złą sławą.
blade-mrn
Przede wszystkim dzięki za pomoc.
Nie jako odpowiadając na pytania.
Teoretycznie ilość pytań można sprawdzić bo są one zapisane w bazie i podczas przeprowadzania testu ich ilość się nie zmienia.
Udzielone odpowiedzi są zapisywane w bazie ale pomysł ze wykorzystaniem tego do wyłączenia wyświetlonych już pytań z zapytania jest nie bardzo, bo co w tedy gdy użytkownik nie udzieli odpowiedzi na jakieś pytanie (taka możliwość istnieje)- to pytanie będzie się mu wyświetlać do puki na nie nie odpowie.
Select distinct() też raczej się tu nie sprawdzi bo pytania odczytywane są pojedynczo za pomocą LIMIT.

Ja za Waszą radą kombinowałem tak... Po wyświetleniu pytania zapisuje jego Id do tablicy zapisanej w sesji w celu późniejszego stworzenia ciągu liczb i przecinków np. 42,43,54. Ciąg ten następnie wstawiam do zapytania, na początku to działa bo wyświetla losowo pytania tyle że test ma 5 pytań a wyświetlają się tylko 3, na pozostałych dwóch stronach pytania się nie wyświetlają.
Tak wygląda fragment kodu o którym pisałem.
  1. $result = $db->query("SELECT * FROM pytania WHERE id_test = ".$rek_test['id_test']." AND id_pytania NOT IN (".$_SESSION['oo'].") ORDER BY RAND() LIMIT $start, 1");
  2. echo '<form action="index.php?id=7" method="POST" id="form" onSubmit="zap_czas(c)">';
  3. echo '<table border="0">';
  4. for ($i=1;$i<=$result->num_rows;$i++)
  5. {
  6. $rek_pyt = $result->fetch_assoc();
  7. $_SESSION['tablica'][]=$rek_pyt['id_pytania'];
  8. for ($t=0;$t<=count($_SESSION['tablica']);$t++)
  9. {
  10. if ($t == 0) {$_SESSION['oo'] = $_SESSION['tablica'][$t];}
  11. if (($t > 0) && ($t < count($_SESSION['tablica']))){$_SESSION['oo'] = $_SESSION['oo'].','.$_SESSION['tablica'][$t];}
  12. }
marcio
  1. $result = $db->query("SELECT * FROM pytania WHERE id_test = ".$rek_test['id_test']." AND id_pytania NOT IN (".$_SESSION['oo'].") ORDER BY RAND() LIMIT $start, 1");


Po pierwsze wydaje mi sie ze nie dziala dlatego ze sesja oo moze zawierac kilka wartosci a ty do zapytanie dajesz cala sesje oo jako jeden ciag.

Reszty kodu nie sprawdzalem ale zrob sobie print_r($_SESSION['oo']) po ostatnim for i zobacz czy mam racje.

blade-mrn
Sesja oo według mojego założenia ma przechowywać tylko jeden ciąg znaków np. 76,34,23 itd. i tak jest.
Sprawdzałem to za pomocą print_r.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.