Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [HTML][MySQL][PHP]tabela w php, jeden do wielu? jak?
Forum PHP.pl > Forum > Przedszkole
sindbad_zeglarz
Hejka
Mam w bazie 3 tabele.
1 tabela - posiadłosci
2 tabela - dane userow
3 tabela - zlaczone id z tabela1 z id_tabela2 (jeden do wielu).

Chcialbym wyswietlić raporcik taki, aby w wyniku był następujący efekt.

Id tabela1 | id tabela 2 | imie tab2 | nazwisko tab 2
1 1 G P
tutaj nie chcę powtarzać tego samego id drugi raz tylko dać inne dane dane z id_tabeli2 , imie i nazwisko.


Przykład: DOM może mieć kilku właścicieli.
Ale jest to jeden DOM = jeden ID a kilka ID wlascicieli.

W SQL-u jakoś nie widzę żeby się to dało zrobić łatwo, chyba że ktoś coś podpowie.
A PHP jak to wyświetlić ?

Podpowiedzcie coś proszę.

Ruch Radzionków
pobierasz z bazy dane za pomocą while a następnie w while pobierasz dane z innej tabeli nie wiem czy dokladnie o to ci chodzi
nospor
@Ruch Radzionków totalnie nieoptymalne rozwiązanie.

@sindbad
Pobierasz jednym zapytaniem niezbędne dane. Z racji, że jeden dom moze miec wielu właścicieli, więc dane domu ci sie powtórzą - normalna sytuacja. Następnie w php grupujesz dane po domie, tam przechowujesz dane właścicieli a następne mając te dane robisz z nimi co ci się tylko podoba. Tutaj, pisałem o tym:
http://nospor.pl/grupowanie-wynikow.html
Shido
Niby bawie się w w SQLu ale takich typowych relacji nie znalazłem.

Ale obeszlem to w taki sposób ( wykorzystam twój przykład z domem ):

Tabela dom:
ID, Nazwa, adres itp.

Tabela wlasciciele:
ID, Dom, imie, nazwisko itp.

i teraz na takiej zasadzie że w kolumnie Dom przy każdym z włascicieli widniej ID domu z tabei dom.

np:
1 | 3 | Jan | Kowalski
2 | 1 | Adam | Nowak
3 | 3 | Maurycy | Bąk

W takim wypadku robiąc raport z włascicieli domów pobierasz sobie z tabeli dom dane koniecznie ID i np. opcjionalnie inne kolumny

i po pobraniu każdego rekordu po ID domu ściągasz sobie z tabeli wlasciciele własicieli gdzie `dom` = '$id'

  1. $zapytanie = "SELECT * FROM `dom`;
  2. $wykonaj = mysql_query ($zapytanie);
  3. while($wiersz=mysql_fetch_array($wykonaj))
  4. {
  5. $id = $wiersz['ID'];
  6. $nazwa = $wiersz['nazwa'];
  7.  
  8. $zapytanie1 = "SELECT * FROM `wlasciciele` WHERE `dom` = '$id';
  9. $wykonaj1 = mysql_query ($zapytanie1);
  10. while($wiersz1=mysql_fetch_array($wykonaj1))
  11. {
  12. $imie = $wiersz1['imie'];
  13. $nazwisko = $wiersz1['nazwisko'];
  14. }
  15. }


Coś w ten deseń.

Można to też zrobic jednym zapytaniem rozległym SQL ale ja osobiście wolę porozbijać to na części i mieć wszystko przejżyste.
nospor
Cytat
Można to też zrobic jednym zapytaniem rozległym SQL ale ja osobiście wolę porozbijać to na części i mieć wszystko przejżyste.
Może to i jest przejrzyste, ale niesamowicie mulaste.
W linku opisałem metodę, która jest o niebo szybsza i może jedynie ciut mniej przejrzysta na pierwszy rzut oka
sindbad_zeglarz
ok a czy ksztalt zapytania ma znaczenie ?
Mam 3 tabele.
tab1 (dom)
id|nazwa|nrdomu
1|dom1|20
tab2 (wlasciciel)
id|imie|nazwisko|adres
tab3
id_dom|id_wlascisciel
1 | 1

lacze je w tej tabeli posredniej tab3.

Jak optymalnie napisac zapytanie?
(
  1. SELECT tab1.id, tab1.nazwa, tab1.nrdomu, tab2.id,tab2.imie,tab2.nazwisko,tab2.adres FROM tab1 tab1, tab2 tab2,tab3 tab3 WHERE tab3.id_dom=tab1.id ;
?

nospor jak to sie ma do Twojego skryptu ?
Bo chyba bym go uzył.
nospor
WE from masz 3 tabele a łączysz tylko dwie. Takie zapytanie wypluje ci masę zbędnych powtórzen bez ładu i składu.

Cytat
nospor jak to sie ma do Twojego skryptu ?
Normalnie, tak jak opisałem w arcie.

Sorki ze tak skrótowo, ale zaraz musze leciec
sindbad_zeglarz
to jak to napisac optymalnie ?
nospor
No toć ci napisałem: skoro masz 3 tabele we FROM to masz je ze sobą połączyć a nie zostawiasz iloczyn kartezjański.

Najlepiej zrób left join
  1. SELECT * FROM tab1
  2. LEFT JOIN tab3 ON tab3.id_dom=tab1.id
  3. LEFT JOIN tab2 ON tab3.id_wlasciciel=tab2.id

To zapytanie zrowci ci dane z tabli dom wraz z przypisanymi do nich wlascicielami. Z racji, ze do jednego domu moze byc kilku wlascicieli, to rekordy domu będą się powtarzać. I w tym właśnie momemcie musisz to obrobić w php. A jak? Dokładnie to masz opisane w arcie co ci dałem do niego linka. Więc teraz wkońcu się z nim zapoznaj, bo jest to dam dokładnie wyjaśnione i podane na przykładzie.
sindbad_zeglarz
Zrobiłem tak dzieka za pomocną dłoń. Doczytałem o joinach, i zaczałem je kumać.

  1. SELECT * FROM dom d
  2. LEFT JOIN tab3 wmd ON wmd.id = d.id
  3. LEFT JOIN wlasciciel w ON wmd.id_wlasciciel = w.id


no i ładnie wyświetla ale oczywiscie powtarza id domu wszedzie tam gdzie jest wlasciciel (wlasciciel moze miec kilka domow).

zastosowanie skryptu kolegi NOSPOR fajnie by rozwiazało sprawę, ktos podpowie:
Jak to zastosować dla mojego przykładu ?

  1. <?php
  2. mysql_connect('localhost','root','') or die(mysql_error());
  3.  
  4. //pobranie wszystkich danych i ich pogrupowanie
  5. $sql = 'SELECT * FROM tabela1 dom
  6. LEFT JOIN tabela3 wmd ON wmd.dom_id = dom.id
  7. LEFT JOIN tabela2 w ON wmd.wlasciciel_id = w.id '; //sortujemy po nazwie kategorii
  8.  
  9. $res = mysql_query($sql) or die(mysql_error());
  10.  
  11. //najpierw pozyskamy niezbędne dane
  12. $wlasciciele = array();
  13. while ($row = mysql_fetch_array($res)){
  14. $cid = $row['id'];
  15.  
  16. //jeśli nie było jeszcze danego wlasciciela to go tworzymy
  17. if (!isset($wlasciciele[$cid]))
  18. $wlasciciele[$cid] = array('name' => $row['nazwisko'], 'wlasciciele' => array());
  19.  
  20. //dodajemy do kategorii kolejne produkty
  21. if (!empty($row['nazwisko'])) //jeśli istnieje produkt
  22. $wlasciciele[$cid]['wlasciciele'][] = array('name' => $row['nazwisko'], 'id'=>$row['id']);
  23. }
  24. print_r($wlasciciele); //do obejrzenia jak wygląda wygenerowana tablica
  25.  
  26. //a teraz wygenerujemy stronę na podstawie uzyskanych danych
  27. echo '<ul>';
  28. foreach ($wlasciciele as $idCat => $category){ //petla, która leci po kategoriach
  29. echo '<li>'.$category['name'].' (liczba wlasciciele: '.count($category['wlasciciele']).')<ul>';
  30. foreach ($category['wlasciciele'] as $nazwisko){ //pętla, która leci po produktach w kategorii
  31. echo '<li>wlasciciel o nazwie <b>'.$nazwisko['name'].'</b> i id <b>'.$nazwisko['id'].'</b></li>';
  32. }
  33. echo '</ul></li>';
  34. }
  35. echo '</ul>';


i jest problem,bo wyświetla
  1. wlasciciel o nazwie nowakowska i id 1
  2. wlasciciel o nazwie nowakowska i id 1
  3. wlasciciel o nazwie nowakowska i id 1
  4. wlasciciel o nazwie nowakowska i id 1
  5. wlasciciel o nazwie taranowska i id 1


już coś lepiej. ale zapętliłem się i nie wiem jak to ugryźć.
Coś nospor poradzisz ?
nospor
1) Chciałeś grupować po domach więc grupuj w php po domach a nie po wlascicielach
2) $cid = $row['id']; tutaj bedziesz mial id z ostatniej tabeli a ciebie interesuje id domu.
wiec nie: select *
a: SELECT *, dom.id domid
i potem: $cid = $row['domid'];

Przyłoż się troszkę do tego a nie poszedłeś na zasadzie KOPIUJ WKLEJ
sindbad_zeglarz
no niby dziala dziekuję Nospor, ale jeszcze nie tak jakbym chciał.
Zrobiłem tak.

SQL
  1. SELECT *,d.id domid,
  2. d.nr_domu numer,
  3. w.id wlaid,
  4. w.nazwisko nazwisko
  5. FROM dom d
  6. LEFT JOIN wlasciciel_ma_dom wmd ON wmd.dom_id = d.id
  7. LEFT JOIN wlasciciel w ON wmdz.wlasciciel_id = w.id
  8. LEFT JOIN gmina g ON d.gmina_id = g.id


Stworzenie tablicy:

  1. $domki = array();
  2. while ($row = mysql_fetch_array($res))
  3. {
  4. $domid = $row['domid'];
  5.  
  6. //jeśli nie było jeszcze danego domu to go tworzymy
  7. if (!isset($domy[$domid]))
  8. $dom[$domid] = array('nazwa' => $row['nr_domu'], 'nrdomu' => $row['numer'], 'dom' => array());
  9.  
  10. //dodajemy do do domu kolejnych wlascicieli
  11. if (!empty($row['nazwisko'])) //jeśli istnieje wlasciciel
  12. $dom[$domid]['wlasciciele'][] = array('wlasciciel' => $row['nazwisko'], 'id'=>$row['wlaid']);
  13. }
  14. print_r($dom);


pętla po tablicy:

  1. foreach ($dom as $domid => $iloscdomkow)
  2. {
  3. echo '<li><b>'.$iloscdomkow['nazwa'].'</b><br>';
  4. echo '<li>'.$iloscdomkow['nrdomu'].'<ul>';
  5. foreach ($iloscdomkow['wlasciciele'] as $allwlasc)
  6. {
  7. echo '<li>Nazwisko Właściciela '.$allwlasc['wlasciciel'].' - id '.$allwlasc['id'].'</li>';
  8. }
  9. echo '</ul></li>';
  10. }
  11. echo '</ul>';


Buduje/wynik:
Nazwisko Właściciela Nowak1 - id 2
135
135
Nazwisko Właściciela Nowak1 - id 2
134
134

i na końcu błąd:
Warning: Invalid argument supplied for foreach() line 78.
foreach ($iloscdomkow['wlasciciele'] as $allwlasc)

Nie wiem czy przez ten bład jest problem, ze powtarza nr domu.

nospor
NIezły tu mamy burdel siostro....

Deklarujes tablice $domki = array(); ale potem używasz $dom a nie $domki
Deklarujesz w indekse 'dom' => array() ale potem uzywasz wlasciciele
Kod html to jakaś sieczka, np:
'<li><b>'.$iloscdomkow['nazwa'].'</b><br>';
LI panie kolego zamyka sie przy pomocy </LI> a nie BR

Wynik wyświetlania ma się nijak do kodu html i nawet nie próbuje go analizować bo mi włos na głowie staje wink.gif
sindbad_zeglarz
hejka smile.gif Nospor pomocy smile.gif

zamieniłem domy z działkami smile.gif ale zasada taka sama. jedna dzialka wiele wlascicieli.

tablica:

  1. $dzialki = array();
  2. while ($wiersz = mysql_fetch_array($zapytanie))
  3. {
  4. $id = $wiersz['dzid'];
  5. echo $id.'.';
  6. if( !isset($dzialki[$id]) )
  7. {
  8. $dzialki[$id] = array(
  9. 'nr_dzialki' => $wiersz['nr_dzialki'],
  10. 'powierzchnia' => $wiersz['powierzchnia'],
  11. 'pow_w_pasie' => $wiersz['pow_w_pasie'],
  12. 'wlasciciele' => array(), // deklaracja jak nie ma zadnego wlasciciela
  13. 'dokumenty' => array() );
  14. }
  15.  
  16. if( !empty($wiersz['nazwisko'] ) )
  17. $dzialki[$id]['wlasciciele'][] = array( 'nazwisko' => $wiersz['nazwisko'] );
  18.  
  19. if( !empty($wiersz['nr_dokumentu'] ) )
  20. $dzialki[$id]['dokumenty'][] = array( 'nr_dokumentu' => $wiersz['nr_dokumentu'] );
  21. }


wyświetlenie tego: tutaj pojawia sie problem.
wyświetla co prawda jeden nr działki ale:
jeśli jest kilka dokumentów i do wlasciciela do jednej działki to tyle raze je dubluje ile jest dokumentów.

jesli jedna dzialka ma jednego wlasciciela - wyswietla ladnie
jesli jedna dzialka ma kilku wlascicieli to wyswietla ok.

---do tego momentu jest ok, ale jesli :
jesli jedna dzialka ma 2 wlascicieli i po 2 dokumenty sa do do wlasciciela to wyswietla zle.

przyklad:

nr dzialki| wlasciciel | dokument
10/1 | heniek 1 | dok1,dok2,dok3
------| heniek 2 | dok1,dok2,dok3
------| heniek 3 | dok1,dok2,dok3

  1. echo '<table border="1" aling=center>
  2. <td>Nr Dzialki</td>
  3. <td>Nazwisko</td>
  4. <td>Nr Dok</td>
  5. </tr>';
  6. foreach ($dzialki as $id => $dzialka)
  7. {
  8. echo '<tr><td>'.$dzialka['nr_dzialki'].'</td>';
  9. echo '<td>';
  10. foreach ( $dzialka['wlasciciele'] as $wlasciciel )
  11. {
  12. echo '<br />';
  13. echo $wlasciciel['nazwisko'].',';
  14. }
  15. echo '</td>';
  16. echo '<td>';
  17. foreach ( $dzialka['dokumenty'] as $dokument )
  18. {
  19. echo '<br />';
  20. echo $dokument['nr_dokumentu'].',';
  21. }
  22. echo '</td></tr>';
  23.  
  24. }
  25. echo '</table>';



nospor
No ale pokaż zapytanie. Skad mam wiedziec co tam nacudowałes
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.