Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Jaka struktura dla bazy?
spenalzo
post 21.11.2003, 18:12:05
Post #1





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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.


--------------------

Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi (1 - 13)
Yacho
post 21.11.2003, 18:18:43
Post #2





Grupa: Zarejestrowani
Postów: 148
Pomógł: 0
Dołączył: 16.06.2003

Ostrzeżenie: (0%)
-----


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
Go to the top of the page
+Quote Post
spenalzo
post 21.11.2003, 18:31:08
Post #3





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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


--------------------

Go to the top of the page
+Quote Post
HaRy
post 21.11.2003, 18:34:19
Post #4





Grupa: Zarejestrowani
Postów: 152
Pomógł: 0
Dołączył: 15.05.2002
Skąd: Łódź

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Jabol
post 21.11.2003, 18:35:21
Post #5





Grupa: Przyjaciele php.pl
Postów: 1 467
Pomógł: 13
Dołączył: 22.02.2003

Ostrzeżenie: (0%)
-----


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ż
Go to the top of the page
+Quote Post
HaRy
post 21.11.2003, 18:38:35
Post #6





Grupa: Zarejestrowani
Postów: 152
Pomógł: 0
Dołączył: 15.05.2002
Skąd: Łódź

Ostrzeżenie: (0%)
-----


to samo mialem na mysli
Go to the top of the page
+Quote Post
spenalzo
post 21.11.2003, 18:53:49
Post #7





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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ć?


--------------------

Go to the top of the page
+Quote Post
Jabol
post 21.11.2003, 21:25:03
Post #8





Grupa: Przyjaciele php.pl
Postów: 1 467
Pomógł: 13
Dołączył: 22.02.2003

Ostrzeżenie: (0%)
-----


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 ).
Go to the top of the page
+Quote Post
adwol
post 21.11.2003, 22:21:25
Post #9





Grupa: Zarejestrowani
Postów: 691
Pomógł: 0
Dołączył: 6.08.2003

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
spenalzo
post 24.11.2003, 19:04:24
Post #10





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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ę
Go to the top of the page
+Quote Post
spenalzo
post 26.11.2003, 19:34:04
Post #11





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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 :/


--------------------

Go to the top of the page
+Quote Post
spenalzo
post 30.11.2003, 03:27:23
Post #12





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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


--------------------

Go to the top of the page
+Quote Post
spenalzo
post 30.11.2003, 16:33:12
Post #13





Grupa: Zarejestrowani
Postów: 2 064
Pomógł: 1
Dołączył: 22.01.2003
Skąd: Poznań

Ostrzeżenie: (0%)
-----


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


--------------------

Go to the top of the page
+Quote Post
Jabol
post 30.11.2003, 17:33:34
Post #14





Grupa: Przyjaciele php.pl
Postów: 1 467
Pomógł: 13
Dołączył: 22.02.2003

Ostrzeżenie: (0%)
-----


zablokowane na życzenie autora
Go to the top of the page
+Quote Post

Closed TopicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 19.07.2025 - 20:55