Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP] Jeden rekord w wielu kategoriach/dodawanie wielu rekordów do kilku kategorii na raz
Forum PHP.pl > Forum > Przedszkole
Przekras
Witam,
potrzebuję zrobić na swoją stronę(a właściwie zrobiłem) skrypt dodający tresci, które mogą należeć do paru kategorii. Zależy mi abym mógł na raz dodawać np 100 rekordów. W bazie mam jedną główną tabelę o nazwie Filmy, struktura:

  1. CREATE TABLE IF NOT EXISTS `Filmy` (
  2. `id_filmu` int(6) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `numer_filmu` int(8) UNSIGNED NOT NULL,
  4. `tytul_filmu` varchar(70) NOT NULL,
  5. `kategoria_filmu` varchar(20) NOT NULL,
  6. PRIMARY KEY (`id_filmu`)
  7. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=60 ;


Oraz każda kategoria zawiera swoje oddzielne tabele, połączone id-em z tabelą główną, każda kategoria będzie wyświetlana na oddzielnej stronie, także taka struktura wydaje mi się najlepsza:
  1. CREATE TABLE IF NOT EXISTS `kategoria8` (
  2. `id_kat8` int(6) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `id_filmu` int(6) UNSIGNED NOT NULL,
  4. PRIMARY KEY (`id_kat8`)
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;


Poniżej kod dodający dane do dwóch tabel na raz(z objasnieniami co chciałem zrobić):
  1. $zapytanie="INSERT INTO `Filmy` (`id_filmu`, `numer_filmu`, `tytul_filmu`, `kategoria_filmu`) VALUES (NULL, '54321', 'tytul1', '9876'), (NULL, '567890', 'tytul2', '9875')";
  2. // i tutaj jeszcze np 50 innych VALUES, kolumna "kategoria_filmu" z danymi np.9876 oznacza że film bedzie wyswietlany w kategoiach o numerach 9, 8, 7 i 6
  3. mysql_query($zapytanie);
  4. $id = mysql_insert_id(); //pobiera id ostatnio dodanego wyniku - DO TEGO PYT 1
  5.  
  6. $kat = "SELECT kategoria_filmu FROM Filmy where id_filmu='$id'"; //wybiera kategorie filmu z tabeli filmy gdzie id_filmu ma numer ostatnio dodanego wyniku
  7. $rezultat = mysql_query($kat)
  8. or die("Query failed");
  9. $wynik = mysql_fetch_array($rezultat);
  10. $wypisanie = $wynik['kategoria_filmu']; //potrzebne aby niżej sprawdzić jakie numery kategorii zawarte w "kategoria_filmu"
  11. $zapisac = mysql_query("INSERT INTO kategoria8 (id_filmu) VALUES ($id)"); //jeżeli spełniony zostanie ponniższy warunek to id z tabeli Filmy zostanie zapisany do tabeli "kategoria8"
  12. if (preg_match("/8/i", "$wypisanie")) //jeżeli w $wypisanie znajduje sie 8 to dzieje sie $zapisac i taki if do każdej kategorii oddzielnie PYTANIE 2
  13. {
  14. echo $zapisac;
  15. }
  16. else
  17. {
  18. }

Ogólnie kod działa jak należy, jednak tylko dla jednego dodanego wyniku.
PYTANIA:
1. Niestety pobierany jest tylko id pierwszego dodanego wyniku i umieszczany w tabeli kategorii, chciałbym aby przy dodawaniu np 50 Values w Insert wszystkie były dodawane od razu do odpowiednich kategorii, da się tak zrobić? Bo dodawanie oddzielnie 50 rekordów byłoby "trochę" uciążliwe. Próbowałem pętle jednak tak kombinowałem że dodałem do dwóch tabel ponad 6 mln rekordów na raz biggrin.gif
2. Czy dałoby radę umieścić wszystko w jednym ifie tzn. sprawdzić jakie cyfry są zawarte w "kategoria_filmu" i umiescic w odpowiednich tabelach kategorii, próbowałem else, ale jeżeli jest spełniony pierwszy warunek to już nie przechodzi do następnego.

Poniżej skrypt wyświetlający wszystkie wiersze z kategorii:
  1. $wypisac = "SELECT *
  2. FROM kategoria8 INNER JOIN Filmy
  3. ON kategoria8.id_filmu = Filmy.id_filmu";
  4. $rezultatt = mysql_query($wypisac);
  5. while ($row = mysql_fetch_array($rezultatt))
  6. {Tutaj kod wyświetlający wszystkie potrzebne rekordy z dwóch tabel}


PYTANIE ogólne:
3. Czy cały ten kod da się jakoś zoptymalizować, może macie jakieś inne sposoby? (ogólnie wszystko działa jak należy oprócz dodawania wielu Values na raz)

Na koniec proszę o wyrozumiałość, wstyd się przyznać ale napisanie tego zajęło mi 2 dni(nie korzystałem z innych skryptów), próbowałem na wiele sposobów i ten wydaje mi się najlepszy.
Pozdrawiam
b4rt3kk
Struktura bazy danych nie jest optymalna. Źle to wszystko rozplanowałeś. Potrzebujesz jednej tabeli filmy, jednej tabeli kategorie oraz jednej tabeli przyporządkowującej film do kategorii. Czyli teoretyczna struktura powinna wyglądać tak:

  1. Tabela movies:
  2. id | title
  3. 1 | kompania braci
  4.  
  5. Tabela categories:
  6. id | name
  7. 1 | wojenne
  8. 2 | thriller
  9.  
  10. Tabela movie_categories:
  11. id | id_movies | id_categories
  12. 1 | 1 | 1
  13. 2 | 1 | 2


Oczywiście w tabeli movie_categories kolumna id jest zbędna, ale można ją zachować dla porządku.
Przekras
W tabeli movie_categories kolumna id_movies (u mnie-numer_filmu) zawierałaby 8 cyfr bo tak długie są numery filmów, i do tego bez żadnej kolejności. Na jednej stronie będę wyświetlał filmy(odnośniki do filmów) tylko z jednej kategorii np. 40 stron po 40 odnośników to daje 1600 dla jednej kategorii(podział na strony przez stronnicowanie), licząc że kategorii będzie 9 a jeden film będzie należał do 3 kategorii tabela „movie_categories” miałaby 43 200 rekordów.

Natomiast w moim rozwiązaniu dane są sczytywane z jednej tabeli kategorii a następnie tytuł i numer filmu ściągany z tabeli Filmy po numerze id, czyli w tym przypadku tabela kategorii zawierałaby te 1600 rekordów, a tabela Filmy 14 400, czyli mniej do przeszukania. Będę wdzięczny jeżeli wytłumaczysz mi dlaczego Twoje rozwiązanie byłoby optymalniejsze(pamiętając że każda kategoria będzie wyświetlana na oddzielnej stronie), bo jak tak rozpisałem to wydaje mi się że moje, ale dobrze się na tym nie znam wink.gif

Pozdrawiam
Damonsson
Jeżeli masz pewność, że zawsze będziesz wykonywał zapytanie pobierające filmy tylko i wyłącznie z jednej kategorii, to Twoje rozwiązanie może mieć jakiś tam głębszy sens, jak będziesz miał milion filmów dla kategorii.
b4rt3kk
Po pierwsze już w samym momencie zapisu danych wykonujesz nadmiarową liczbę zapytań. Po drugie preg_match dodatkowo spowalnia wstawianie rekordów (swoje zajmuje czasowo, zmień na str_pos jak musisz tak robić). Już lepiej (o ile jesteś pewien, że zostajesz przy takiej strukturze bazy) oddzielić poszczególne id np. średnikiem. Wtedy wystarczy explode. Przykład poniżej.

  1. $zapytanie="INSERT INTO `Filmy` (`id_filmu`, `numer_filmu`, `tytul_filmu`, `kategoria_filmu`) VALUES (NULL, '54321', 'tytul1', '9876'), (NULL, '567890', 'tytul2', '9;8;7;5')";
  2. mysql_query($zapytanie);
  3. $kat = "SELECT kategoria_filmu FROM Filmy where id_filmu='$id'"; // na co to zapytanie? kategorię masz już znaną w momencie inserta? całkiem zbędne
  4. $rezultat = mysql_query($kat) or die("Query failed");
  5. $wynik = mysql_fetch_array($rezultat);
  6. $wypisanie = explode(';', $wynik['kategoria_filmu']);
  7.  
  8. foreach ($wypisanie as $id_tab) {
  9. $zapisac = mysql_query("INSERT INTO kategoria{$id_tab} (id_filmu) VALUES ($id)");
  10. }


No i co do samej zasadności użycia 3 tabel. Nie chodzi tutaj o liczbę rekordów, tylko o uniwersalność rozwiązania. Wyobraź sobie, że dodajesz lub usuwasz kategorię. I co wtedy? Wszystko nagle się rypnie, bo albo będziesz musiał modyfikować wszystkie wpisy z tabeli filmy, albo baza utraci spójność. A tak, usuwasz kategorię, usuwasz wszystkie dowiązania i baza dalej działa bez zarzutu. Gdy będziesz chciał dodać kolejną kategorię to będziesz musiał dodawać kolejne tabele dla tej kategorii.

A tak to masz jedno proste zapytanko żeby pobrać całą daną kategorię (pownno być dosyć szybkie), a napewno bardziej uniwersalne, na potrzeby www (potrzebujesz tylko 1 i tej samej podstrony, a zmieniasz tylko parametr w GET):

  1. SELECT
  2. *
  3. FROM movies m
  4. JOIN movies_categories mc ON m.id = mc.id_movies
  5. JOIN categories c ON c.id = mc.id_categories
  6. WHERE c.id = $id_cat;

mmmmmmm
Cytat(Przekras @ 15.10.2014, 19:45:51 ) *
W tabeli movie_categories kolumna id_movies (u mnie-numer_filmu) zawierałaby 8 cyfr bo tak długie są numery filmów, i do tego bez żadnej kolejności. Na jednej stronie będę wyświetlał filmy(odnośniki do filmów) tylko z jednej kategorii np. 40 stron po 40 odnośników to daje 1600 dla jednej kategorii(podział na strony przez stronnicowanie), licząc że kategorii będzie 9 a jeden film będzie należał do 3 kategorii tabela „movie_categories” miałaby 43 200 rekordów.

Coś źle liczysz... Jeśli będziesz miał 1600 filmów i 9 kategorii, a każdy film będzie należał do 3 kategorii, to tabela movie_categories będzie miała 1600*3 rekordów. Czyli jakieś 4800.

Cytat(Przekras @ 15.10.2014, 19:45:51 ) *
Natomiast w moim rozwiązaniu dane są sczytywane z jednej tabeli kategorii a następnie tytuł i numer filmu ściągany z tabeli Filmy po numerze id, czyli w tym przypadku tabela kategorii zawierałaby te 1600 rekordów, a tabela Filmy 14 400, czyli mniej do przeszukania. Będę wdzięczny jeżeli wytłumaczysz mi dlaczego Twoje rozwiązanie byłoby optymalniejsze(pamiętając że każda kategoria będzie wyświetlana na oddzielnej stronie), bo jak tak rozpisałem to wydaje mi się że moje, ale dobrze się na tym nie znam wink.gif

A tu nie wiem, skąd wziąłeś 1600 kategorii? Naprawdę sądzisz, że fimy da się opisać aż tyloma kategoriami?
@b4rt3kk ci wszystko ładnie rozpisał. Spróbuj.
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.