Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Jaka struktura dla bazy?
Forum PHP.pl > Forum > Bazy danych
spenalzo
Mam za zadanie zrobić serwis w stylu Friendster.com.
Schemat ideowy połączeń wygląda tak:
Pan X zaprasza 10 znajomych, w tym pana Y, który ma 34 znajomy, a wsród nich jest pan Z, który posiada 73 znajomych, wsród których jest pan A itd itd...
Czyli w skrócie: znajomi mojego znajomego są jednocześnie moimi znajomymi - i tak w pętli aż do końca - kurcze, aż ciężko to opisać :|

I w związku z tym mam pytanie: w jaki sposób najlepiej zaprojektować tabelę z ID użytkowników, żeby to było szybkie i wydajne? Chodzi o jedną tabelę , która by zawierała połączenia między użytkownikami.
Yacho
imho tak :
ID|name|FriendsID|ParentFriends iD|



ID - wiadomo
name - tez wiadmomo
Friends ID - IDki osob ktore pan NAME ma wpisane jako przyjaciol
ParentFriendsID - IDki osob ktore maja wpisanego pana Name jako friendsa...

troche to zagmatwane ale male i dziala biggrin.gif (powinno smile.gif smile.gif
spenalzo
Yacho - wlasnie o takim czymś myślałem, ale w troche zmienionej postaci

Kod
+----+------+----------+

| ID | MyID | IDFriend |

+----+------+----------+

  1      34       345

  2      34      4365

  3      34       574

  4      34      1065

  5    4365     76322

  6    4365      2574

......


gdzie MyID to moje ID a dalej ID moich przyjaciół, a IDFriend to ID przyjaciół ludzi o ID z pola MyID.

Czy dobrze uważam?

Jakby mogło wyglądać przykładowe zapytanie na wyciagnięcie ID wszystkich osób powiązanych ze mnąquestionmark.gif
HaRy
wydaje mi sie, ze tak jest najwydajniej. eq. jeszcze wywalic kolumne ID, a MyID | IDFriend oznaczyc jako primary key.

choc nie wiem. ale gdzies czytalem, ze tak wlasnie sie robi w takim szkielecie bazy.
Jabol
a IMHO to można zrobić tak
people
id, name - tutaj wszystko jasne

friendshpis
person_id, like_id
person_id - id osoby ( references people bleble... )
like_id - osoby ktore lubi ( dla kazdej osoby nowy wpis )

potem superpętelka ( rekurnecyjna oczywiści ) i już
HaRy
to samo mialem na mysli
spenalzo
Ja też myślałem o 2 tabelach, ale tutaj chodziło o tą jedną tabelę-łącznik smile.gif Dzięki.

A czy da sie napisać takie zapytanie co na raz pobierze wszystkie ID-ki czy trzeba to juz przez php robić?
Jabol
Cytat
A czy da sie napisać takie zapytanie co na raz pobierze wszystkie ID-ki czy trzeba to juz przez php robić?
raczej tak. chyba, że by się pobawić ( tzn. zrobić sobie hardcorowego zajoba ) z pozapytaniami ( ale to tylko dal określonej głębokości by umiało ).
adwol
Dwie uwagi:
- Przy tego typu bazach musisz sobie określić jakie zapytania będziesz wykonywał w ogóle, jakie najczęściej i pod to optymalizować schemat bazy. Nigdy nie będzie tak, aby baza była optymalna w każdym przypadku.
- Należy znaleźć złoty środek między wydajnością a wielkością bazy i redundancją. W praktyce można zapomnieć o ideałach typu trzecia postać normalna czy brak redundancji. Oczywiście da się bazę w ten sposób zaprojektować, ale jej wydajność będzie daleka od ideału.

Schemat który zaproponował Jabol jest naturalnym, książkowym rozwiązaniem, ale to co opisujesz jest drzewem (a nawet grafem), a to już nie jest najszczęśliwsza struktura do trzymania w relacjach.

Generalnie, ustal:
- ile może być maksymalnie zagłębień powiązań znajomości (być może nieskonczoność)
- jakie informacje będziesz chciał od bazy uzyskiwać

Wtedy będzie można myśleć nad schematem.
spenalzo
Cytat
Generalnie, ustal:
- ile może być maksymalnie zagłębień powiązań znajomości (być może nieskonczoność)
- jakie informacje będziesz chciał od bazy uzyskiwać


Ad.1 zakłądam, że nieskończoność, ale być może będzie ograniczenie do x poziomów (na razie nie wiem)

Ad.2 wystarczą mi same ID osób i/lub ich liczba - resztę sam dopracuję
spenalzo
Hmm tak myśalałem sobie nad zapytaniem i nic nie mogę wymyślić. Natomiast szukanie ID z php w takiej drzewiastej strukturze to masakra... 90 sekund nie starcza :/
spenalzo
Więc tak - po kilku dyskusjach i wielu próbach doszedłem do takiego schematu i kodu jak poniżej - ale gdzieś tu jest bład logiczny... :| rolleyes.gif

Dobra... mam wiec taka oto tabele:
Kod
myID | friendID | lev

gdzie lev to poziom "zaglębienia".

Stworzylem sobie także przykladowa tabele users, gdzie mam ID i username.

Oto kod, jaki wykorzystuje do dodawania danych:
[php:1:df3c513c2f]<?php
if(empty($_GET["myID"]))
{
$_GET["myID"]=186;
}
function dodaj_osobe($myID,$friendID,$lev="0")
{
#$prev= ($lev<1 ? 0 : ($lev<2 ? 1 : $lev-1));
if($myID!=$friendID)
{
if($lev<1)
{
$sql="SELECT count(myID) FROM god_connections WHERE myID='".$myID."' AND friendID='".$friendID."'";
}
else
{
$sql="SELECT count(myID) FROM god_connections WHERE myID='".$myID."' AND friendID='".$friendID."' AND lev='".$lev."'";
}
$q=mysql_query($sql);
$ile=mysql_result($q,0);
if($ile<1)
{
if(!mysql_query("INSERT INTO god_connections (myID,friendID,lev) VALUES (".$myID.",".$friendID.",".$lev.")"))
{
return(mysql_error());
}
}
}
return(true);
}

if(empty($_GET["add"]) && empty($_GET["list"]))
{
$q=mysql_query("SELECT * FROM god_users");
while($t=mysql_fetch_array($q))
{
echo "<a href=?add=".$t["id"]."&myID=".$_GET["myID"].">".$t["username"]."</a><br>";
}
}
elseif($_GET["add"]>0)
{
$q=mysql_query("SELECT * FROM god_connections WHERE friendID=".$_GET["myID"]." AND lev < 3") or die(mysql_error());
$i=0;
while($t=mysql_fetch_array($q))
{
$ids[$i]["myID"]=$t["myID"];
$ids[$i]["friendID"]=$t["friendID"];
$ids[$i]["t"]="m";
$ids[$i]["lev"]=$t["lev"];
$i++;
}
$q=mysql_query("SELECT * FROM god_connections WHERE myID=".$_GET["myID"]." AND lev < 3") or die(mysql_error());
while($t=mysql_fetch_array($q))
{
$ids[$i]["friendID"]=$t["friendID"];
$ids[$i]["myID"]=$t["myID"];
$ids[$i]["t"]="f";
$ids[$i]["lev"]=$t["lev"];
$i++;
}
echo "<pre>";
print_r($ids);
echo "</pre><br><br>";
echo dodaj_osobe($_GET["myID"],$_GET["add"]);
dodaj_osobe($_GET["add"],$_GET["myID"]);
foreach($ids AS $key=>$v)
{
$v["lev"]++;
if($v["t"]=="m")
{
dodaj_osobe($v["myID"],$v["friendID"],$v["lev"]);
}
else
{
dodaj_osobe($v["friendID"],$v["myID"],$v["lev"]);
}
}

}
?>[/php:1:df3c513c2f]
Wiem, że to można było prościej napisać - ale tutaj chodzi tylko o sprawdzenie działania i przejrzystość (czyli powtórzenia) jest ważna.
Zamieszczam całość bo może znajdzie się ktoś kto by to sprawdził - bede dozgonnie wdzięczny smile.gif
spenalzo
Więc problem jest taki:
za pierwszym dodaniem przy pomocy powyżzego kodu w tabeli mam takie coś:
Kod
  myID   friendID  lev

   186    106      0

   106    186      0

Czyli zgodnie z planem, ale przy drugim dodaniu (już innego usera):
Kod
myID  friendID  lev

186  106   0

106  186   0

186  153   0

153  186   0

106  186   1

a zamiast 106 | 186 powinno być chyba 153 | 186 oraz 106 |153, 153|106 itd - czyli każdy z każdym (+ odpowieni poziom)...
Jabol
zablokowane na życzenie autora
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.