Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP][SQL]Dzienniczek ucznia, czy nie dało by się lepiej?
Forum PHP.pl > Forum > Przedszkole
cycofiasz
Witam, zrobiłem sobie skrypt dzienniczka ucznia. Zasady działania nie muszę za pewne tłumaczyć smile.gif.

Mam 2 tabele w mysql:




Skliciłem taki oto skrypt:
  1. <?php
  2. echo '<table style="border-collapse: collapse;" border="1">'."\n";
  3. echo ' <caption style="caption-side: top;padding: 2px;"><b>Oceny ucznia nr. 20</b></caption>'."\n";
  4. echo ' <tr align="center"><td width="30"><strong>Lp.</strong></td><td width="200"><strong>PRZEDMIOT</strong></td><td width="200"><strong>OCENY</strong></td>'."\n";
  5.  
  6. // pobieramy listę przedmiotów
  7. $sql_przdmioty = mysql_query ("SELECT `przedm_id`,    `przedm_nazwa` FROM `dzienniczek_przedmioty`");
  8.  
  9. while ($row = mysql_fetch_array($sql_przdmioty))
  10. {    
  11.    $oceny=''; $o=''; //resetowanie zmiennych
  12.    $sql_oceny = mysql_query ("SELECT `ocena_stopien` ,`ocena_waznosc` FROM `dzienniczek_oceny` WHERE `ocena_przedm_id` = '$row[przedm_id]'");
  13.    while ($row2 = mysql_fetch_array($sql_oceny))
  14.    {
  15.        if($row2[ocena_waznosc] == '1') $o = '<span style="color:red">'.$row2[ocena_stopien].'</span>'; // kolorowanie sprawdzienów
  16.        elseif($row2[ocena_waznosc] == '2') $o = '<span style="color:blue">'.$row2[ocena_stopien].'</span>'; //kolorowanie innych ocen
  17.        $oceny .= $o.', ';
  18.    }
  19.    
  20.    echo " <tr><td>$row[przedm_id]</td><td>$row[przedm_nazwa]</td><td>$oceny</td></tr>\n";
  21. }
  22.  
  23. echo '</table>'."\n";
  24. ?>


co dało taki rezultat (taki jak ma być)




Jak zauważyliście skrypt ten pobiera najpierw listę przedmiotów i podczas każdego przebiegu pętli jest wykonywane zapytanie o oceny do tego przedmiotu... Nie wydaje się wam się też że to jest nieoptymalne? Jak pobrać to wszystko bez zawierania w pętlach zapytań do sql?
zegarek84
  1. SELECT dzienniczek_przedmioty.przedm_id, dzienniczek_przedmioty.przedm_nazwa, dzienniczek_oceny.ocena_stopien, dzienniczek_oceny.ocena_waznosc
  2. FROM dzienniczek_przedmioty LEFT JOIN dzienniczek_oceny ON dzienniczek_przedmioty.przedm_id=dzienniczek_oceny.ocena_przedm_id
  3. ORDER BY dzienniczek_przedmioty.przedm_id

jeszcze jedno zauważyłem że "dokładasz" do ocen - wyświetlając w pętli to zapytanie zrób sobie przed petlą jakąś zmienną i w pętli sprawdzaj czy jej wartość jest różna od id_przedmiotu - jesli różna wyświetlisz cały wiersz, jeśli taka sama to pomiń prawie cały rekord i dopisz ocenę - po tym na koniec pętli przypisz wartość tej zmiennej co porównujesz wartość id_przedmiotu....

mam na myśli taką sytuację zwróconą z bazy:

Kod
przedm_id     ||przedm_nazwa    || ocena_stopien    || ocena_waznosc
    1    ||    j.pol    ||    10/20    ||    1
    1    ||    j.pol    ||    3    ||    2
    2    ||    j.ang    ||    5    ||    2


lub w 2 zapytaniach prawie tak jak zrobiłeś tyle że pobież odrazu pełne tabele te co potrzebujesz i przyrównaj to w php gdyż odwołanie w pętli do bazy nie jest najlepszym pomysłem...
cycofiasz
Ten 2 sposób wydaje się chyba sensowniejszy.

Czyli najpierw wykonuję zapytanie sql_oceny
  1. SELECT ocena_przedm_id , ocena_stopien , ocena_waznosc FROM `dzienniczek_oceny`


Przekazuję wynik do tablicy $oceny
  1. <?php
  2. while ($row = mysql_fetch_array($sql_oceny)) $oceny[]=$row
  3. ?>


Otrzymam taką zawartość tablicy $oceny:
  1. <?php
  2. (
  3.    [0] => Array
  4.        (
  5.            [0] => 2
  6.            [ocena_przedm_id] => 2
  7.            [1] => 5
  8.            [ocena_stopien] => 5
  9.            [2] => 2
  10.            [ocena_waznosc] => 2
  11.        )
  12.  
  13.    [1] => Array
  14.        (
  15.            [0] => 3
  16.            [ocena_przedm_id] => 3
  17.            [1] => 5
  18.            [ocena_stopien] => 5
  19.            [2] => 1
  20.            [ocena_waznosc] => 1
  21.        )
  22.     ...dalsze wartości...
  23. )
  24. ?>


A potem pobieram listę przedmiotów z bazy i przy każdym przebiegu pętli, zamiast dawać kolejne zapytanie do mysql, filtruję tablicę $oceny za pomocą pętli foreach:
  1. <?php
  2. //pobieramy wszystkie oceny
  3. $sql_oceny = mysql_query ("SELECT ocena_przedm_id , ocena_stopien , ocena_waznosc FROM `dzienniczek_oceny`");
  4.  
  5. while($row1 = mysql_fetch_array($sql_oceny))
  6. $oceny[] = $row1;
  7.  
  8.  
  9. // pobieramy listę przedmiotów
  10. $sql_przdmioty = mysql_query ("SELECT `przedm_id`,    `przedm_nazwa` FROM `dzienniczek_przedmioty`");
  11.  
  12. while ($row2 = mysql_fetch_array($sql_przdmioty))
  13. {    
  14.    $ocenki = '';
  15.    foreach($oceny as $wartosc)
  16.    {
  17.        if($wartosc[ocena_przedm_id] == $row2[przedm_id])
  18.        {
  19.            $ocenki .= $wartosc[ocena_stopien].', ';
  20.        }
  21.    }
  22.    
  23.    echo " <tr><td>$row2[przedm_id]</td><td>$row2[przedm_nazwa]</td><td>$ocenki</td></tr>\n";
  24. }
  25.  
  26. echo '</table>'."\n";
  27. ?>

Dobrze zrozumiałem? Czy to jest wydajniejsze niż dawanie zapytań przy każdym przedmiocie? Ta tablica $oceny z czasem może stać się większa...
zegarek84
sory że tak puźno odpisuję ale dopiero dziś znalazłem czas (w końcu po zaliczeniach ^^)
Cytat(cycofiasz @ 17.01.2009, 10:46:58 ) *
Dobrze zrozumiałem? Czy to jest wydajniejsze niż dawanie zapytań przy każdym przedmiocie? Ta tablica $oceny z czasem może stać się większa...

to i tak bedzie wydajniejsze od zapytań w pętli do bazy myql - choć bawiąc się bazą sqlite i używając sesji miałbyś podobny efekt winksmiley.jpg...

ja proponuje dane które "sciągasz" z bazy danych zapisywać do tablicy wielo wymiarowej mniej więcej o takiej konstrukcji:
Kod
Array
(
    [$id_przedm] => Array
        (
            [nazwa_id_przedm] => j.pol
            [ocena] => Array
                (
                    [0] => Array
                        (
                            [stopien] => 2
                            [warznosc] => 1
                        )

                    [1] => Array
                        (
                            [stopien] => 3
                            [warznosc] => 2
                        )
                )
        )
)

głównie dlatego żeby nie przeszukiwać w pętli całej tablicy ocen tylko jakby to posortować.... z kolei jesli tych ocen miało by być multum (za bardzo obciążające pamięć przez operacje na tablicach) to mógłbyś w pętli pobierać większą liczbę tych ocen sortując po id_przedmiotu i korzystając z LIMIT w zapytaniu a potem następna działkę do tablicy pamiętając o zwolnieniu pamięci tego co już się "zoperowało" czyli kasowaniu fragmentów starej tablicy przez urzycie funkcji unset()... pobieranie każdej oceny w petli z bazy to trochu by to spowolniło wszystko (w ostatecznosci jeśli aż tak dużo ocen to porcjami - choć wątpię by było aż tak dużo) i operacja jak już wspomniałem na tablicach - ale jednak pasuje przypisać i operować na tablicy wielowymiarowej żeby nie "przelatywać i sprawdzać" w pętli za każdym razem tych ocen - poprostu posortować podczas wpisów do tablicy i operować jakby to nazwać na "podtablicach"...

jeszcze raz przepraszam że tak puźno odpisuję i o ile to przeczytasz mam nadzieje że zrozumialeś - przegladam tematy w których się wypowiadam więc jeśli coś napiszesz to za jakiś czas znowu tu zajrzę winksmiley.jpg

PS.
przez $id_przedm mam na myśli te cyferki dla przedmiotu (można by w sumie dac inna konstrukcję i odrazu nazwę przedmiotu tutaj zamiast wewnątrz tego fragmentu tablicy ale jak już kto woli winksmiley.jpg - pozatym chcący tu odrazu dawać nazwę przedmiotu to pasowało by trzymać w pamięci podczas przepisywania ocen tablicy z przedmiotami i przeszukiwać żeby zamiast id_przedmiotu pod ocenami urzywać nazwy przedmiotu - ale raczej to wiele nie zmieni winksmiley.jpg... czyli dla 2 przedmiotów takich co masz mniej więcej tablica wyglądała by tak:
Kod
Array
(
    [1] => Array
        (
            [nazwa_id_przedm] => j.pol
            [ocena] => Array
                (
                    [0] => Array
                        (
                            [stopien] => 10/20
                            [warznosc] => 1
                        )

                    [1] => Array
                        (
                            [stopien] => 3
                            [warznosc] => 2
                        )
                )
    [2] => Array
        (
            [nazwa_id_przedm] => j.ang
            [ocena] => Array
                (
                    [0] => Array
                        (
                            [stopien] => 5
                            [warznosc] => 2
                        )    
                )
                
)
)
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.