Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][SQLite]Tabele bazy danych, jedna czy kilka? Filozofia...
Forum PHP.pl > Forum > Przedszkole
arstherapia
Witajcie ponownie,

dzisiaj natknąłem się na kolejny problem: jak zaplanować efektywnie strukturę bazy danych?

W jednej tabeli mam:

1. Nazwa_filmu
2. Opis_filmu
3. Okładka (link)
4. Autor
5. Autor_bio
6. Autor_fot (link)
7. Wersja_jezykowa
8. Cena
9. Premiera ( tak, nie )

i chciałem dodać kategorię, ale uzmysłowiłem sobie, że jedna komórka może przyjmować tutaj wiele wartości:
terapia poznawcza, terapia behawioralna, etc.

Poczytałem i znalazłem taką zasadę, aby nie wciskać wielu wartości w jedną komórkę, więc rozwiązaniem jest
osobna tabela, a tam np.

1. Kategoria_ID
2. Nazwa_kategorii

Czy to ma sens? Jak pożenić zapytania i wyświetlenia pól z tabel ?

To może autorów też wrzucić w osobną tabelę? Wtedy byłyby trzy:

1. Filmy
2. Kategorie
3. Autorzy

A w przyszłości:

4. Klienci
5. Zamówienia

Pozdrawiam,

Rafał

--------------------------
Tak sobie dalej myślę, że jeśli utworzę kilka tabel, to będę mieć między nimi relacje, czyli będę musiał nauczyć się i używać inner join itp. ...
Prościej byłoby np. zamiast tabeli - "kategorie" utworzyć osobną kolumnę w tabeli filmy i tam wpisywać kategorię.

Zamotałem się.
luniak
  1. Tak sobie dalej myślę, że jeśli utworzę kilka tabel, to będę mieć między nimi relacje, czyli będę musiał nauczyć się i używać inner join itp. ...
  2. Prościej byłoby np. zamiast tabeli - "kategorie" utworzyć osobną kolumnę w tabeli filmy i tam wpisywać kategorię.


Owszem było by prosciej, ale zarazem mmniej wydajnie smile.gif
3 tabele:

1. Filmy
2. Kategorie
3. Autorzy

Są chyba, w Twoim przypadku, najelpszym rozwiązaniem [ najoptymalniejszym ], a nauczenie się używanie join'ów nie jest znów takie problematyczne smile.gif
zidek
Jeśli każdy film ma jednego autora, a każdy autor ma tylko jeden film to wystarczą tabele film, kategoria, autor. Podobnie jest z kategoriami.

Ale jeśli jeden autor będzie miał 4 filmy, to w tamtym układzie będziesz miał w 4 wierszach te same dane (autor, autor_bio, autor_fot nie zmienią się).

Film:
- id (Primary Key)
- nazwa
- opis
- okładka - w jakiej formie ma być okładka? jeśli jest to obrazek to lepiej przechowuj tylko id/nazwę obrazka, a nie cały link
- wersja_jezykowa
- cena
- premiera

Kategoria:
- id (Primary Key)
- kategoria_nazwa

Film_kategoria:
- id (Primary Key)
- film_id
- kategoria_id

Autor:
- id (Primary Key)
- nazwa
- bio
- foto - to też img? lepiej zapisuj zdjęcia np. w katalogu img/autor/ i zapisuj pliki jako id.png (1.png, 512.png itd)? zamiast dodatkowej kolumny wystarczy wtedy odwołanie się do id

Film_autor:
- id (Primary Key)
- film_id
- autor_id

Niekoniecznie im więcej tabel tym lepiej, ale należy unikać powtarzania się danych. Jeśli w jednej kategorii jest kilka filmów, to warto tylko raz trzymać w bazie nazwę kategorii, a do filmów przypisać tylko id. W przypadku zmiany nazwy takiej kategorii nie będziesz musiał zmieniać połowy swojej bazy, wystarczy wtedy jeden update.
mmmmmmm
Jeśli mowa o filmach to jeszcze lepiej zrobić jeszcze głębszy podział.
Zawody:
id PK
nazwa (rezyser, scenarzysta, aktor, producent,...)

Zamiast tabeli Autor, tabela Osoby smile.gif Struktura jw.
Zamiast Film_autor tabela Ludzie_Filmu:
id PK,
Film_id,
Osoba_id,
Zawod_id

Np. Mel Gibson w Filmie "Dorwać Gringo" jest scenarzystą i aktorem, a w "Pasji" jest rezyserem, scenarzysta i producentem.

phpion
@mmmmmmm:
Po co w tej tabeli osobna kolumna na klucz główny? Wystarczyłoby oprzeć klucz główny na tych 3 kolumnach i po sprawie (bo taka trójka i tak powinna być unikalna). Jeśli założyć, że 1 osoba w 1 filmie może mieć tylko 1 zawód to nawet wystarczyłoby tylko na Filma_id i Osoba_id. Do tego każda kolumna kluczem obcym.
nospor
w Film_kategoria tez nasz oddzielne ID i a dobrą sprawę też niepotrzebnie.

Zas co do zawodow, to zdarza się, że w jednym filmie dana osoba jest zarowno rezyserem jak i aktorem lub inne kombinacje
phpion
Zgadza się, dlatego napisałem "jeśli założyć" wink.gif
nospor
No to jesli zalozyc, ze interesuje nas tylko autor, to rozbijanie na zawody jest bez sensu i wracamy do punktu wyjscia wink.gif
Jak juz sie cos robi, to robmu to porządnie. Zimy jeszcze nie ma by cos zakladac wink.gif
arstherapia
O cholera !

Bardzo Wam dziękuję, muszę teraz przetrawić i zrozumieć, co do mnie piszecie:)

( Kupiłem wczoraj Mistrz PHP. Pisz nowoczesny kod - więc może przeczytam rozdział o bazach danych
i jeszcze raz przeczytam Wasze odpowiedzi )

Wszystko wydaje się cholernie skomplikowane, dopóki się nie oswoję z czymś.
Piszecie, że należy unikać powtarzania się danych, a np. cena będzie się powtarzać, bo 80 %
filmów ma dwie ceny - 99 i 199 zł.
Tak samo wersja językowa - "angielska" i "polskie napisy" - też będą się powtarzać.

Ps. Jedna osoba często ma kilka filmów, np.

Otto Kernberg:
1. Superwizja
2. Psychoterapia psychoanalityczna
3. Terapia zaburzeń osobowości ,

a z kolei każdy film często jest w kilku kategoriach, np.

Otto Kernberg - Superwizja : kategorie
a) superwizja
cool.gif terapia psychoanalityczna
c) filmy z napisami PL

Dobra, trochę pohisteryzowałem, biorę się teraz do nauki smile.gif

Dziękuję !
nospor
Cytat
Piszecie, że należy unikać powtarzania się danych, a np. cena będzie się powtarzać, bo 80 %
filmów ma dwie ceny - 99 i 199 zł.
Nie o takie powtarzanie chodzi.
Przykladowo nie ma sensu w kazdym filmie pisac wszystkich danych autora: Imie, nazwisko, adres, tel, - gdyz to jest bezsensownym powtarzaniem calej masy danych.
Po to sie robi tabele Osoba by w niej zapisac RAZ dane osoby, a pozniej tylko przez ID sie do niej odwolywac. A co gdy osoba zmieni tel? Bedziesz latał po wszystkich rekordach i zmienial? A jak masz jeden rekord w tabeli osoba, to zmieniasz tel. tylko tam i wszystko gra.

Tak, samo nie ma sesnu za kazdym razem pisac "angielska" i "polskie napisy". Tutaj masz wiele opcji do wyboru:
1) Tworzysz tabele WERSJE z rekordami: angielska, polskie napisy, blabla, a w filmie przekazujesz tylko ID wersji zamiast calego tekstu.
2) Zamiast pola varchar, walisz tinyint i zamiast tekstow "angielska" i "polskie napisy dajesz 1,2,3,4.... gdzie 1 to "angielska" , gdzie 2 to polskie napisy itd
3) zamiast polavarchar czy tinyint dajesz pole ENUM - poczytaj w manualu mysql.
mmmmmmm
Cytat(phpion @ 4.09.2014, 09:41:09 ) *
@mmmmmmm:
Po co w tej tabeli osobna kolumna na klucz główny? Wystarczyłoby oprzeć klucz główny na tych 3 kolumnach i po sprawie (bo taka trójka i tak powinna być unikalna). Jeśli założyć, że 1 osoba w 1 filmie może mieć tylko 1 zawód to nawet wystarczyłoby tylko na Filma_id i Osoba_id. Do tego każda kolumna kluczem obcym.

Po co klucz główny? By był.
Czemu na jednym polu? Bo szybszy (i zapis, i odczyt)
A czy jedna osoba może mieć tylko jeden zawód w filmie? Pewnie może, ale wtedy do takiej bazy nie dodasz mnóstwa informacji. Np. tego, że Eddie Murphy w filmie "Rodzina Klumpów" był 8*aktorem. http://www.filmweb.pl/film/Gruby+i+chudszy...umpów-2000-1077 Z tego powodu też nie ma klucza na tych trzech kolumnach. Bo to zarys tabeli był - mogą tam być również inne informacje. Np. rolę jaką odtwarzał.
phpion
Oczywiście w tym o czym pisze ~nospor należy zachować umiar i zdrowy rozsądek. Równie dobrze można by zamiast:

aktor [id, imie, nazwisko]

dać

aktor [id, imie_id, nazwisko_id]
imie [id, wartosc]
nazwisko [id, wartosc]

co jednak byłoby kompletnie bez sensu, aczkolwiek z punktu widzenia unikania redundacji danych byłoby logiczne. Musisz "wyczuć" co rozbijać na osobne tabele (powiedzmy: słownikowe), a co nie.

// Edit:
@mmmmmmm - jak w takiej sytuacji realizujesz aktualizację danych? Ja w przypadku tego typu tabel po prostu usuwam dane (tutaj: dla filmu) i wrzucam je na nowo. W takiej sytuacji ID'ki niepotrzebnie byłyby zwiększane. Poza tym by zachować spójność danych i tak musiałbyś założyć ograniczenie unikalności na te kolumny. Ponadto nie wiem do czego ona miałaby być wykorzystana - nie będziesz przecież pobierał rekordu po jego id. Moim zdaniem dodatkowa kolumna id jest zbędna.
nospor
Cytat
Oczywiście w tym o czym pisze ~nospor należy zachować umiar i zdrowy rozsądek. Równie dobrze można by zamiast:
Hehe, jeszcze nie widzialem takiego szalenca co by tak robil, ale fakt, dobrze o tym wspomniec smile.gif

No i jak pisalem, nie trzeba zaraz ze slownikiem wyjezdzac. Mozna uzyc chocby ENUM

Cytat
@mmmmmmm - jak w takiej sytuacji realizujesz aktualizację danych? Ja w przypadku tego typu tabel po prostu usuwam dane (tutaj: dla filmu) i wrzucam je na nowo. W takiej sytuacji ID'ki niepotrzebnie byłyby zwiększane. Poza tym by zachować spójność danych i tak musiałbyś założyć ograniczenie unikalności na te kolumny. Ponadto nie wiem do czego ona miałaby być wykorzystana - nie będziesz przecież pobierał rekordu po jego id. Moim zdaniem dodatkowa kolumna id jest zbędna.

W tym wypadku mmmmmm moze miec racje. Chocby przez dodanie roli dla ediego, ktory gral 8 roznych rol. Tutaj ID moze miec sens.

Sensu zas ID nie ma w tabeli film_kategoria, bo tam raczej juz zadne inne dane nie dochodzą.
arstherapia
W footerze sklepu, jak już go sobie napiszę, umieszczę:

Platforma sklepu powstała tylko i wyłącznie dzięki pomocy osób z forum php.
Special Thx to All.

------------
Wiecie co, ja to chyba muszę sobie rozrysować.
Biorę psa na spacer, przemyślę, a potem rozrysuję.



-------------------------
To tak na moje by wyglądało:

Tabela : filmy

1. Tytuł
2. Autor (pole powiązane z tabelą osoby - 1 )
3. Opis
4. Kategoria główna ( pole powiązane z tabelą kategorie )
5. Kategoria pomocnicza ( pole powiązane z tabelą kategorie )
6. Okładka
7. Autor_bio ( pole powiązane z tabelą osoby - 2 )
8. Autor_fot ( pole powiązane z tabelą osoby - 3 )
9. Cena
10. Wersja językowa

Tabela : osoby

1. Imię i nazwisko
2. Biografia
3. Zdjęcie

Tabela : kategorie

1. Poznawcza
2. Humanistyczna
3. Analityczna
4. Superwizja
5. Terapia par i rodzin
itd.

Rozwiązanie to ma w sobie ograniczenie, że jeden film może być w dwóch kategoriach.

Wychodzi mi z tego pięć "joinów" czy jak to nazywacie, które jakoś muszę wygenerować za każdym razem.
W związku z tym dużo pracy ( a raczej nauki ) przede mną.

Czytałem jeszcze coś o tabelach łączących, takich dodatkowych, ale to już chyba za ostra jazda dla mnie...

Ciągle chodzi mi po głowie pokusa, tak jak kiedyś chciałem całkiem uniknąć sql'a, to teraz chciałbym to utrzymać
w jednej tabeli, nawet wbrew redundancji danych. W końcu to góra 200 filmów, ruch niewielki...
Turson
Jak na moje dodaj primary keys typu film_id, osoba_id, kategoria_id
Wtedy w filmy dodajesz osoba_id i wiążesz filmy.osoba_id = osoby.osoba_id, kategorie też wiążesz po id a nie wpisuejsz nazwy na sztywno.
Jak zmienisz nazwę kategorii przez literówkę, to wtedy zmieni się wszędzie bo masz powiażane id, a nie wpisane nazwy
arstherapia
Dobrze, Turson, dziękuję !
nospor
Cytat
Rozwiązanie to ma w sobie ograniczenie, że jeden film może być w dwóch kategoriach.
Powinienies zrobic tabele łączącą jak ci pisalismy...

Cytat
Ciągle chodzi mi po głowie pokusa, tak jak kiedyś chciałem całkiem uniknąć sql'a, to teraz chciałbym to utrzymać
w jednej tabeli, nawet wbrew redundancji danych. W końcu to góra 200 filmów, ruch niewielki...
Jak juz sie uczysz, to rob to porządnie i nie wydziwiaj
arstherapia
Cytat(nospor @ 4.09.2014, 17:52:33 ) *
Jak juz sie uczysz, to rob to porządnie i nie wydziwiaj


Dobrze, Szefie.


Chyba mam jakiś czeski błąd, albo źle myślę:

  1. $result = $db->query('SELECT * FROM filmy, kategorie WHERE filmy.Kategoria = kategorie.rowid = 1');


Chciałem wylistować wszystkie filmy z tabeli filmy, wybierając te pozycje, które w polu "Kategoria" mają wpisaną jedynkę,
która ma odpowiadać polu "rowid" też numerek 1.

Ale, listuje wszystkie. Pewnie źle rozumiem JOINy, albo mam czeski błąd. Pewnie oba. Naprowadźcie proszę.

W sumie to bezsensu to moje zapytanie:)

Przecież mogę wylistować z jednej tabeli, wybierając tylko where Kategoria = 1 .... To po co mi ta druga tabela z kategoriami w takim razie? I jak przypisać dwie kategorie do jednego filmu?

Błądzę w ciemnościach... wszędzie mrok.

----------------------------------------------------
Dobra, to kumam tak:

1. Druga tabela tylko w celach redundancji.
2. Listuję tylko z jednej tabeli, filmy. Ale nawet wtedy listuje mi wszystkie pozycje:

  1. $result = $db->query("SELECT * FROM filmy
  2. WHERE Kategoria='1'");


Ale ja głupi jestem:)

Dałem w złym miejscu... teraz kod wygląda tak:

  1. <?php
  2. $db = new PDO('sqlite:ars.sqlite');
  3. ?>
  4.  
  5. <div class="section_header">
  6. <div class="row"><div class="col-lg-12">
  7. <h3>Premiery z polskimi napisami</h3>
  8. <hr />
  9. </br>
  10. </div></div>
  11. </div>
  12.  
  13. <div class="container my-container">
  14.  
  15.  
  16. <!-- Drugi rząd -->
  17. <div class="row">
  18. <?php
  19. $result = $db->query("SELECT Okladka FROM filmy WHERE Kategoria='1'");
  20. foreach($result as $row)
  21. { echo '<center><div class="col-lg-2"><img src="'.$row['Okladka'].'" class="picColor"/> </div></center>';}
  22. ?>
  23. </div>
  24. <div class="row">
  25. <?php
  26. $result = $db->query("SELECT Nazwa FROM filmy WHERE Kategoria='1'");
  27. foreach($result as $row)
  28. { echo '<center><div class="col-lg-2"><a class="btn btn-default" href="product_view.php?Nazwa=' . ( $row['Nazwa'] ) . '">Zobacz film</a></div></center>';}
  29. ?>
  30. </div>
  31. </div>


Niestety, nadal nie wiem, jak przypisać dwie kategorie do jednego filmu.
Czy dopuszczalne jest w polu tabeli podanie dwóch, trzech wartości, np. [1, 3, 5] ?
nospor
Po pierwsze: pisalem juz ci kiedys, ze jak chcesz pobrac dwie kolumny z tabeli, to masz robić TYLKO JEDNO ZAPYTANIE a nie dwa.... Jesli tego nie ogarniasz, to zanim pojdziesz dalej ogarnij to wkoncu. Masz zamiar powielac ten blad do konca zycia? Jesli nie wiesz, jak to zrobic, to nie ignoruj tego, tylko dopytaj.
Masz wykonac jedno zapytanie pobierajace dane jakie chcesz. Dane te masz zapisac do tablicy, a potem sobie operuj po tej tablica gdzie i jak ci sie podoba.

Cytat
Niestety, nadal nie wiem, jak przypisać dwie kategorie do jednego filmu.
Czy dopuszczalne jest w polu tabeli podanie dwóch, trzech wartości, np. [1, 3, 5] ?

Pisalismy ci juz na samym poczatku w jaki sposob przypisuje sie wiele kategorii do filmu. Czemu nie przejrzysz tematu od poczatku, tylko powielasz pytanie, gdzie odpowiedz juz padla? Ja rozumiem, że moze jestes poczatkujacy, ale to nie zwalnia cię z analizowania informacji, ktore dostajesz. Skoro odpowiedz juz raz padla, to skup sie na niej i ewentualnie dopytaj jesli nie rozumiesz jak to wykonac, a nie znowu zaczynasz kombinowac jakby nikt ci nie udzielil odpowiedzi wczesniej na to pytanie.
arstherapia
I dostało mi się słuszny OPR od nospor'a smile.gif

Faktycznie, nie wczytałem się wystarczająco w Wasze posty. Przepraszam.

To, czego nie rozumiem, to tworzenie dodatkowych tabel z już istniejących.

Film_kategoria:
- id (Primary Key)
- film_id
- kategoria_id


Rozumiem, że jakimś zapytaniem ( poleceniem ) tworzę osobną tablicę Film_kategoria
i tam umieszczam dane. Ale jak?

Mam tabelę "kategorie":

Id Nazwa
1 Kat1
2 Kat2
3 Kat3

Mam też tabelę "filmy":

Id Nazwa Kategoria
1 Pierwszy Kat1 (?)
2 Drugi Kat2 (?)

Nadal nie wiem, jak to pożenić i stworzyć Film_kategoria. Czy mam tam dane wpisywać ręcznie? Jeśli tak, to jakie dane mam podać w "filmy" - kolumna kategoria ?

Mam wrażenie, że czegoś bardzo, bardzo nie łapię, czegoś bardzo fundamentalnego.

---------------
Przeczytałem uważnie posty oraz zakupiłem książkę w Empiku : PHP i MySQL, od nowicjusza do wojownika ninja.

Po lekturze postów i jednego z rozdziałów rozjaśniło mi się w głowie to, co piszecie o tabelach łączących ( lookup tables smile.gif
oraz typach relacji jeden do wielu, wiele do jednego itd.

Oficjalnie dziękuję Wszystkim za niepodawanie kodu na tacy smile.gif
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.