Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][MySQL] struktura bazy danych dla testu
Forum PHP.pl > Forum > Przedszkole
perszing2045
Witam Was, mam do Was pytanie jak do speców, chce zrobić jakąś bazę testów online.

Testy już działały bo zapis odbywał się do plików .txt gdzie ich struktura była następująca:

/nazwa testu
--/nazwa testu/info.ini //informacje o ilości pytań zamkniętych i otwartych oraz o ilości dopuszczalnych odpowiedzi
--//nazwa testu/1.txt // pytanie 1 oraz kolejne linijki z odpowiedziami
--//nazwa testu/2.txt // pytanie 2 oraz kolejne linijki z odpowiedziami
...
--//nazwa testu/xx.txt // pytanie xx oraz kolejne linijki z odpowiedziami

Rozwiązywanie było dobre ale dla jednorazowego uruchomienia, zapis wyników też odbywałby się do plików txt ale tutaj poszedłem po rozum do głowy i stwierdziłem że przesiądę się na MySQL i teraz jest problem:

Jaką strukturę bazy danych zrobić, tak aby baza działa w miarę wydajnie i bezproblemowo przy 10 jak i przy 200 testach zapisanych w niej.

Zastanawia mnie taka struktura:


Tabela user | userid | login | haslo |

Tabela testy | testid | nr testu | nazwa testu | ilosc pytan | ilosc odpowiedzi |

Tabela odpowiedzi | odpid |odpowiedz | nr odpowiedzi | nazwa testu | poprawna |

Tabela wyniki | wynikid | login | nazwa testu |


Zastanawia mnie czy takie rozwiązanie ma jakiś sens, może ktoś już pisał jakiś test na bazie pytań, gdzie nie ma określonych na sztywno ilości pytań i odpowiedzi?

Mam nadzieje ze jakoś zrozumiale opisałem moją sprawę, liczę na propozycję a nie na lincz z Waszej strony;)
Chcę poznać Wasze wizję a nie dostać gotowca;)
Pozdrawiam
JR
bercow
jezeli dobrze rozumiem, to ja to widze tak


  1.  
  2. CREATE TABLE user (
  3. iduser INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, /*oczywiscie id AI*/
  4. login TEXT NULL,
  5. haslo TEXT NULL,
  6. PRIMARY KEY(iduser)
  7. );
  8.  
  9. CREATE TABLE test (
  10. idtest INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, /*jw.*/
  11. name TEXT NULL, /*nazwa testu*/
  12. odp_1 TEXT NULL, /*odpowiedzi 1-4, w zalenosci ile ma byc*/
  13. odp_2 TEXT NULL,
  14. odp_3 TEXT NULL,
  15. odp_4 TEXT NULL,
  16. poprawna INT NULL, /* ktora poprawna a wiec 1-4 */
  17. PRIMARY KEY(idtest)
  18. );
  19.  
  20. CREATE TABLE wyniki (
  21. idwyniki INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  22. iduser INTEGER UNSIGNED NOT NULL, /*id usera ktory zaliczal*/
  23. idtest INTEGER UNSIGNED NULL, /* id zaliczanego testu*/
  24. zaliczyl BOOL NULL, /* czy zaliczyl */
  25. PRIMARY KEY(idwyniki),
  26. INDEX wyniki_FKIndex1(user_iduser),
  27. INDEX wyniki_FKIndex2(test_idtest)
  28. );
perszing2045
bercow Dzięki za odpowiedz, jednak widzisz, Twój skrypt przewiduje tylko 4 odpowiedzi na sztywno, a ja myślę żeby samemu ustalać liczbę odpowiedzi do każdego testu (np test1: 20 pytań po 6 odpowiedzi, test2: 10 pytań po 8 odp -> oczywiście nie wiem ile będzie max odpowiedzi:/ ) i tutaj jest problem:/

A może rzeczywiście czas iść z prądem i tworzyć jedynie 4 odpowiedzi do każdego pytania a nie stwarzać sobie problemy:/
Pozdrawiam
ToAr
zamiast

  1. CREATE TABLE test (
  2. idtest INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, /*jw.*/
  3. name TEXT NULL, /*nazwa testu*/
  4. odp_1 TEXT NULL, /*odpowiedzi 1-4, w zalenosci ile ma byc*/
  5. odp_2 TEXT NULL,
  6. odp_3 TEXT NULL,
  7. odp_4 TEXT NULL,
  8. poprawna INT NULL, /* ktora poprawna a wiec 1-4 */
  9. PRIMARY KEY(idtest)
  10. );


stwórz 2 tabele

  1. CREATE TABLE test (
  2. idtest INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, /*jw.*/
  3. name TEXT NULL, /*nazwa testu*/
  4. PRIMARY KEY(idtest)
  5. );
  6.  
  7. CREATE TABLE test_odp (
  8. idodp INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, /*jw.*/
  9. idtest INTEGER UNSIGNED NULL, /* id zaliczanego testu*/
  10. odp TEXT NULL,
  11. poprawna INT NULL, /* czy poprawna 0 - nie, 1 - tak */
  12. PRIMARY KEY(idodp)
  13. );


pmir13
Bardziej naturalne wydaje się oddzielenie pytań i odpowiedzi w osobnych tabelach.
Bo jeśli testy mają zmienną liczbę pytań, a każde pytanie może mieć dowolną liczbę odpowiedzi, przy czym dane pytanie występuje tylko w jednym teście, a pytania mogą być trudniejsze i łatwiejsze ( różna ilość punktów ), to nasuwa się struktura:

testy: id, nazwa, czas_trwania
pytania: id, id_testu, tresc, typ, ilosc_punktow
odpowiedzi: id, id_pytania, odpowiedz, prawidlowa

Nie jest to jakaś bardzo skomplikowana struktura, a nie ogranicza nam funkcjonalności.
Pytania mogą być różnego typu, na przykład jednokrotnego wyboru - wtedy wyświetlamy selecta lub radio, albo wielokrotnego - checkboxy.
Sama ilość pytań czy odpowiedzi dla testu wynika bezpośrednio z zawartości w bazie, nie trzeba tego dodatkowo zapisywać w tabeli testy, zwłaszcza że wymagałoby to zmiany za każdym razem gdybyśmy dodawali lub usuwali pytanie lub odpowiedź. Czasami warto mieć takie wartości zapisane po to by było wydajniej, ale w tym przypadku zysk będzie za mały by robić sobie dodatkowe problemy z utrzymaniem spójności bazy. Mysql dobrze sobie radzi z bazami, w których pojedyncze tabele dostają kilkadziesiąt tysięcy nowych rekordów dziennie, przy bazie, w której jest 200 testów po kilkanaście pytań i odpowiedzi to naprawdę nie trzeba się zbytnio martwić wydajnością. Ogólnie trzymając się zasady dla każdej tabeli id typu int, auto_increment, bez null jako klucz primary, plus ewentualnie indeksy na pola wykorzystywane w porównaniach, nawet bardzo skomplikowane zapytania łączące kilka tabel będą natychmiastowe przy tej ilości rekordów jeśli tylko sprzętu nie wzięliśmy z muzeum.

Co do użytkowników i wyników to jest ok, pod warunkiem, że wyniki liczymy na bieżąco i nie interesują nas informacje które dokładnie odpowiedzi użytkownik w danym teście zaznaczył. Polecam jednak odnosić się w wynikach przez id testu a nie jego nazwę. Jeżeli chcemy zmienić nazwę testu to najlepiej by to było w jednym właściwym miejscu, co by nie martwić się czy zmieniliśmy już wszędzie czy też może gdzieś coś zostało.
perszing2045
Dzięki Koledzy za pomoc, temat stał się bardziej jasny dla mnie jako dla raczkującego w temacie MySQL.

Oczywiście jeżeli inni mają jakąś propozycję rozwiązania to z chęcią poczytam;)


Pozdrawiam
bercow
te zaznaczone przez usera odpowiedzi, tez nie są głupie, umożliwiają podsumowanie, sprawdzenie błędów, i mogą zapobiegać oszustwom.
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.