Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Projekt bazy danych
Forum PHP.pl > Forum > Bazy danych
symonides
Cześć,
mam do zaprojektowania bazę danych, która będzie tyczyła się nieruchomości, czyli np. domy, mieszkania, działki. Każdy z tych typów nieruchomości ma jakąś część danych wspólną, np. kraj, województwo, miasto, cenę, itp. Czyli to by była tabela główna o przykładowej nazwie realestates. Co dalej ? Każdy następny typ to kolejna tabela (czyli osobna na dodatkowe informacje o mieszkaniach, domach, czy działek)? Wydaje mi się to troszkę niewygodne, bo gdy dojdzie kolejny typ, np. magazyny to trzeba dodać kolejną tabelę + oczywiście jakieś zmiany w kodzie. Drugi pomysł to prócz tabeli realestates, tabela details, która będzie przechowywać wszystko to co miało być w tych dodatkowych tabelach (np. kolumna media - tylko działki, piwnica - tylko mieszkania, itd. w jednej tabeli).

Dodam, że operacje będą wykonywane na kilku/kilkunastu tysiącach rekordów.

Który pomysł jest waszym zdaniem lepszy? Może macie jakieś propozycje?

Pozdrawiam
bww
Moim zdaniem najlepiej utworzyć słowniki typów nieruchomości, krajów, województw, miast itd. i w tabelce z danymi nieruchomości odwoływać się do nich poprzez dodanie kluczy obcych.
W tym wypadku łączenie tabel nawet na kilkunastu tysiącach rekordu nie będzie stanowiło problemu, bo klucze będą zaindeksowane.

Myślę, że informacje na temat normalizacji bazy danych pozwolą ci znaleźć złoty środek.

symonides
Chodzi Ci o to, że w tabeli realestates mam przykładowo kolumnę type w której określam, czy chodzi o mieszkanie, lokal, czy działkę oraz kolumnę object_id w której jest klucz obcy do któregoś z rekordów z tabel flats, locals, itd?
bww
Chodziło mi mniej więcej o coś takiego (PK - klucz główny, FK - klucz obcy):


CITY
----------
id_city PK
id_country FK
city_name

TYPE
----------------
id_type PK
type_name

REALESTATES
----------------
id_rel PK
id_type FK
id_city FK
price
surface
...
symonides
Wielkie dzięki. Wydaje się to być o wiele bardziej sensowne, ale jeszcze dla pewności dopytam, czy całość ma wyglądać tak?

REALESTATES
----------------
id_rel PK
id_type FK
id_city FK
price
surface
...

FLATS
----------------
id
realestate_id
...

LOCALS
----------------
id
realestate_id
...

...

Czy wszystkie detale upychamy w tabeli realestates?
bww
Nie wiem, czy dobrze rozumiem Twoją koncepcję. Chcesz rozbić rodzaje nieruchomości na poszczególne tabele?
symonides
No właśnie tak mam od początku i wydaje mi się to dziwne, dlatego też pytam, aby się upewnić jak byś to rozwiązał. Generalnie w niczym mi to pracy nie ułatwia, troszeczkę nawet utrudnia ten nadmiar(?) tabel, ale chciałbym to zrobić tak, żeby przy rozbudowie bazy o kolejne typy nieruchomości jak najmniej ucierpieć.
bww
Wyobraźmy sobie, że mamy aplikację biura nieruchomości. Pracownik ma ekran dodawania nowej pozycji i tam między innymi listę wybieraną "typ nieruchomości".
Przy tworzeniu osobnej tabeli dla każdego typu, z góry musiałbyś założyć, która pozycja odpowiada danej tabeli, a listę wybieraną uzupełnić ręcznie w aplikacji. Nie dość, że będzie przy tym dużo zabawy, to w przypdku, gdy pracownik zażyczy sobie dodania kolejnego typu, będziesz musiał powielać żmudne czynności.

Nie łatwiej by było, żeby lista wybierana uzupełniała się sama korzystając z danych z tabeli, a przy dodaniu nowego typu wystarczyłoby wykonać tylko jeden INSERT?

Łatwiej, dlatego są relacje.

TYPE
----------------
id_type PK
type_name

REALESTATES
----------------
id_rel PK
id_type FK - tutaj zdefiniowany jest typ nieruchomości; gdybyś chciał określić typ danej nieruchomości, wykonujesz złączenie tabel (poniżej)
id_city FK
price
surface
...

  1. SELECT r.id_rel, t.type_name FROM REALESTATES r
  2. JOIN TYPE t ON r.id_type = t.id_type


W samej aplikacji listę wybieraną można zdefiniować jako pętlę wybierającą wszystkie dane z tabeli TYPE. Dla użytkownika widoczna jest kolumna type_name, a dla aplikacji kolumna id_type przekazywana przez np. $_POST.
Dla użytkownika, który będzie mógł tylko oglądać aplikację (np. klient biura) też możesz wyrzucić wszystko na ekran za pomocją pętli (np. menu, w którym pozycjami są rodzaje nieruchomości, jeżeli mają być to elementy graficzne, możesz w bazie przypisać ścieżkę grafiki do danego typu nieruchomości), a jego wybór przekazywać do aplikacji przy pomocy $_GET (tylko pole id_type) i potem w aplikacji używać powyższego select-a modyfikując go o wymagane kolumny i dodając przy tym warunek WHERE dla odpowiedniego id_type.
symonides
Nie wiem tylko czy wziąłeś pod uwagę, to że różne typy nieruchomości mają mieć różne parametry, np. działki (typ działki - enum(budowlana, rolna, ...)), mieszkania (ilość poziomów, czy są balkony, piętro, ile pięter ma budynek, ...) i to z tym mam największy problem, nie mam pomysłu jak to rozbić (z tego co zrozumiałem to o tym akurat nie pisałeś), a sposób z wieloma tabeli, tak jak z resztą wspomniałeś to masochizm.
bww
Nie wziąłem.

Dodatkowo stworzyłbym tabelki:

PARAMETERS
----------------
id_parameters PK
param_name
--unit (jako wartość np. m2)

TYPE_PARAMETERS
---------------------
id_parameters FK
id_type FK
tutaj kluczem głównym będzie złożenie kluczy obcych

Do tabelki REALESTATES można dodać kolumny, które będą wspólne dla każdego typu nieruchomości np. cena + kolumnę parametrs (o tym za chwilę), do tabeli PARAMETERS można wpisać wszystkie parametry nieruchomości, które są rózne, a w tabelce TYPE_PARAMETERS będzie znajdować się połączenie tabel PARAMETERS i TYPE co spowoduje, że każdemu rodzajowi nieruchomości będzie można określić oddzielny parametr.

W aplikacji np. na ekranie dodawania nowej nieruchomości, wypisałbym wszystkie parametry pasujące do danego typu nieruchomości, a po uzupełnieniu przez użytkownika tworzył tablicę i zapisywał do tabeli REALESTATES (kolumna parameters) korzystając z funkcji serialize().

Ewentualnie stworzyć jeszcze jedną tabele (nazwijmy ją TYPE_PARAM_REALE), która będzie tworzyła relację tabeli REALESTATES i TYPE_PARAMETERS, wtedy funkcja serialize() nie będzie konieczna, bo w tej tabeli dla każdej nieruchomości będzie kilka rekordów z parametrem i jego wartością:

TYPE_PARAM_REALE
---------------------
id_TYPE_PARAMETERS
id_rel
value

id_TYPE_PARAMETERS i id_rel tworzą klucz główny

Realizować można to np. tak:
Pracownik wybiera typ nieruchomości 'mieszkanie', które w naszej tabeli TYPE ma id = 1. Wypisujemy mu parametry jakie są dostępne dla tego typu:
  1. SELECT id_TYPE_PARAMETERS, param_name FROM parameters p
  2. JOIN type_parameters tp ON p.id_parameters = tp.id_parameters AND tp.id_type = 1

Pracownik dodaje nową nieruchomość, uzupełnia odpowiednie pola, a w aplikacji wykonują się dwa INSERTY jeden dodający nieruchomość do tabeli REALESTATES, drugi INSERT do tabeli TYPE_PARAM_REALE (id_TYPE_PARAMETERS wyciągnąłeś zapytaniem powyżej, id_rel można wyciągnąć przez mysql_insert_id(), value to wartość wpisana w formularzu).

Może ktoś doświadczony wypowie się jeszcze...
symonides
Wielkie, dzięki. Posiedzę nad tym przez weekend i zobaczę co z tego wyjdzie, ale wydaje mi się, że tak jak piszesz będzie o niebo lepiej niż tak jak pisałem na początku.

Z racji tego, że temat dalej tyczy się projektowania baz danych i relacji. Chodzi o relacje między ulicami, miastami, kodami pocztowymi, województwami (prowincjami) i krajami.

  1. CREATE TABLE streets (
  2. id,
  3. name
  4. )
  5.  
  6. CREATE TABLE towns (
  7. id,
  8. name,
  9. province_id
  10. )
  11.  
  12. CREATE TABLE provinces (
  13. id,
  14. name,
  15. country_id
  16. )
  17.  
  18. CREATE TABLE postcodes (
  19. id,
  20. postcode
  21. )
  22.  
  23. CREATE TABLE countries (
  24. id,
  25. name,
  26. symbol
  27. )


Chodzi o to, aby np. w tabeli customers id ulicy, miasta(?) wiedzieć z jakiego jest kraju, czy województwa. Największy problem mam dopasować do tego ulice i kody pocztowe, tzn. nie wiej jak zrobić w tym miejscu relacje... Jak wy rozwiązalibyście ten problem?
bww
Jedna miejscowość może mieć tylko jeden kod pocztowy, jeden kod pocztowy może być przypisany tylko do jednej miejscowości. Mamy relację 1:1, a więc rezygnujemy z tabeli postcodes i kody wrzucamy do towns.
Z oddzielnej tabeli dotyczącej ulic zrezygnował bym i wrzucił kolumnę adres (ulica i numer lokalu) do tabeli opisującej nieruchomość, ewentualnie można podzielić na ulica, numer domu, numer lokalu. Co prawda warto normalizować, ale osobna tabela dotycząca ulic chyba nie przyniesie korzyści.

countries -> provinces -> towns -> customers

CUSTOMERS
--------------
id_custmomer
id_provinces
name
(...)


Jeżeli chcesz zobaczyć z jakiego jest kraju to robisz JOINA tych kilku tabel

  1. SELECT * FROM customers cu
  2. JOIN towns t ON cu.id_town = t.id_town
  3. JOIN provinces p ON t.id_provinces = p.id_provinces
  4. JOIN countries co ON p.id_countries = co.id_countries
symonides
W sumie to może być wiele kodów pocztowych do jednego miasta smile.gif http://kodypocztowe.com/miasta-kody-poczto...o/warszawa.html

To teraz tak, w tabeli customers mamy id miasta (town_id). Połączenie kodów pocztowych z miastami - relacja n:m. Jeżeli podanie kodu pocztowego będzie wymagane (jeszcze tego nie wiem), to żeby znać miasto, województwo, itd. to kolumnę town_id w tabeli customers można zamienić na postcode_id. Co do ulic to w sumie nie najgorszy pomysł żeby trzymać je bezpośrednio w tabeli customers/realestates, ale warto też zwrócić uwagę, że konkretne ulice przypadają pod jakiś kod pocztowy. Troszkę tego jest. Nie bardzo jeszcze wiem jak bardzo szczegółowe informacje będą wymagane, dlatego też rozpatruje różne mozliwości jak to zrobić.
bww
Cytat(symonides @ 22.02.2012, 00:09:47 ) *
W sumie to może być wiele kodów pocztowych do jednego miasta smile.gif http://kodypocztowe.com/miasta-kody-poczto...o/warszawa.html


No tak, mieszkałem w małym mieście i przyzwyczaiłem się do jednego kodu smile.gif.

Cytat(symonides @ 22.02.2012, 00:09:47 ) *
To teraz tak, w tabeli customers mamy id miasta (town_id). Połączenie kodów pocztowych z miastami - relacja n:m. Jeżeli podanie kodu pocztowego będzie wymagane (jeszcze tego nie wiem), to żeby znać miasto, województwo, itd. to kolumnę town_id w tabeli customers można zamienić na postcode_id. Co do ulic to w sumie nie najgorszy pomysł żeby trzymać je bezpośrednio w tabeli customers/realestates, ale warto też zwrócić uwagę, że konkretne ulice przypadają pod jakiś kod pocztowy. Troszkę tego jest. Nie bardzo jeszcze wiem jak bardzo szczegółowe informacje będą wymagane, dlatego też rozpatruje różne mozliwości jak to zrobić.


Czyli w zasadzie kod pocztowy wiąże się z ulicą i być może numerem domu, a nie z miastem. To znacznie utrudnia sprawę. Szkoda chyba czasu na szukanie i analizę, szczególnie gdy aplikacja ma dotyczyć wielu krajów.
Najgorsze z tego wszystkiego to uzupełnianie słowników. Jeżeli nie masz przyzwoitej listy to ciężko będzie to zrealizować.

Pewnie lepiej będzie w aplikacji zostawić użytkownikowi pola (miasto, kod_pocztowy, ulica) do ręcznego uzupełnienia, skryptem Java autouzupełniać w przypadku, gdy np. dane miasto istnieje już w bazie, a gdy nie dodawać do bazy.

Kwestia jak wielka ma być aplikacja, ile nieruchomości będzie się w niej znajdować. Na wielkości rzędu 1 - 10k pewnie nie będzie się opłacać tak kombinować, a użytkownik nie odczuje dyskomfortu uzupełniając ręcznie pole adres (wraz z kodem pocztowym i miastem).

Najważniejsze to wziąć ołówek, dużą kartkę i wszystko sobie rozrysować (tabele, relacje, kolumny, wymagane dane, dane opcjonalne, orientacyjna liczba rekordów w danej tabeli itd.). Bez dobrego projektu, ciężko stworzyć dobrą aplikację.



symonides
Zgadzam się, że bez projektu ciężko o dobra aplikację. Nieruchomości będzie raczej rzędu kilkaset z różnych krajów (gównie z Polski) smile.gif Chyba zrobię tak jak piszesz. Dzięki za wszystkie rady.

Pozdrawiam
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.