[ fatality1 @ 18.05.2009. 14:35 ] @
eh ovako

imam zadatak da uradim social network , sto i nije neki problem , znaci malo dizajna , malo sql-a i to bi se dalo rijesiti , ali ima jedna dodatna stvar , koja je i sustina tog zadatka a to su "veze" medju korisnicima.naime , npr. imam 4 korisnika , korisnik 1 , korisnik 2 , korisnik 3 i korisnik 4 , i sada korisnik 1 je prijatelj sa korisnikom 2 , korisnik 2 je prijatelj sa korisnikom 3 a korisnik 3 je prijatelj sa korisnikom 4 , sto bi u sql nekako ovako izgledalo :


ID friend-ID
1 2
2 3
3 4

eh tu je sada problem , jer bih trebao prikazati kako od korisnika 1 doci do korisnika 4 , odnosno preko koje relacije se korisnik 1 i korisnik 4 znaju (moze biti i vise puteva , npr. korisnik 1 zna korisnika 2 i korisnika 3 , a korisnik 2 i korisnik 3 znaju korisnika 4)
uglavnom ja sam nasao nesto na netu , ali je uradjeno na temelju novog oracle dok tih opcija nema u sql-u

(npr. ovakva relacija)

1->2->3->4

poslije bih ovo jos trebao nekako graficki predstaviti , ali mi je prvo bitno da shvatim kako ove relacije dobiti

i eto zamolio bih ako neko zna neki sajt ili tutorial ili ako ima neke upute da podijeli na forumu:)

a evo sta sam ja nasao :

http://www.tutorials.de/forum/1380293-post8.html
[ Goran Rakić @ 18.05.2009. 15:07 ] @
http://stackoverflow.com/quest...-linked-list-in-mysql-database
[ bogdan.kecman @ 18.05.2009. 15:14 ] @
koji deo ovoga sto je Thomas napisao ti nije jasan ? realno, moze da se izbaci t_friend.id iz t_friend tabele i da t_friend.userid i t_friend.friendid budu kompozitni primarni kljuc (sto bi bilo bolje nego kako je sada i malo bi ubrzalo sve operacije nad bazom), ali generalno, to je to ... onaj upit bi morao malo da se prebudzi za mysql ...

Code:


mysql> drop table t_user;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> CREATE TABLE t_user (id int auto_increment primary key, name varchar(255) NOT NULL);
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql> CREATE TABLE t_friend (userid int NOT NULL, friendid int NOT NULL, PRIMARY KEY  (userid, friendid));
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql> INSERT INTO `t_user` (name) VALUES ('pera'), ('mika'), ('zika'), ('laza'),('selma'),('zozefina'),('enena');
Query OK, 7 rows affected (0.00 sec)
Records: 7  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `t_friend` VALUES (1,2),(1,3),(1,5),(2,3),(2,5),(2,6),(3,7),(3,4);
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> -- koga zna pera
mysql> SELECT k1.friendid FROM t_friend k1 WHERE k1.userid=1;
+----------+
| friendid |
+----------+
|        2 | 
|        3 | 
|        5 | 
+----------+
3 rows in set (0.00 sec)

mysql> -- do koga sve pera moze da dodje preko prvog kolena
mysql> SELECT k1.friendid, k2.friendid FROM (SELECT t_friend.friendid FROM t_friend WHERE t_friend.userid=1) k1 JOIN t_friend k2 ON (k2.userid = k1.friendid);
+----------+----------+
| friendid | friendid |
+----------+----------+
|        2 |        3 | 
|        2 |        5 | 
|        2 |        6 | 
|        3 |        4 | 
|        3 |        7 | 
+----------+----------+
5 rows in set (0.00 sec)

mysql> -- ili ovako, mada je ovo prethodno bolje
mysql> SELECT k1.friendid, k2.friendid FROM (SELECT t_friend.friendid FROM t_friend WHERE t_friend.userid=1) k1 LEFT JOIN t_friend k2 ON (k2.userid = k1.friendid);
+----------+----------+
| friendid | friendid |
+----------+----------+
|        2 |        3 | 
|        2 |        5 | 
|        2 |        6 | 
|        3 |        4 | 
|        3 |        7 | 
|        5 |     NULL | 
+----------+----------+
6 rows in set (0.00 sec)

mysql> -- ocemo trece koleno ?
mysql> SELECT k1.friendid, k2.friendid, k3.friendid FROM (SELECT t_friend.friendid FROM t_friend WHERE t_friend.userid=1) k1 JOIN t_friend k2 ON (k2.userid = k1.friendid) JOIN t_friend k3 ON (k3.userid = k2.friendid);
+----------+----------+----------+
| friendid | friendid | friendid |
+----------+----------+----------+
|        2 |        3 |        4 | 
|        2 |        3 |        7 | 
+----------+----------+----------+
2 rows in set (0.00 sec)

mysql> -- ili ovako?
mysql> SELECT k1.friendid, k2.friendid, k3.friendid FROM (SELECT t_friend.friendid FROM t_friend WHERE t_friend.userid=1) k1 LEFT JOIN t_friend k2 ON (k2.userid = k1.friendid) LEFT JOIN t_friend k3 ON (k3.userid = k2.friendid);
+----------+----------+----------+
| friendid | friendid | friendid |
+----------+----------+----------+
|        2 |        3 |        4 | 
|        2 |        3 |        7 | 
|        2 |        5 |     NULL | 
|        2 |        6 |     NULL | 
|        3 |        4 |     NULL | 
|        3 |        7 |     NULL | 
|        5 |     NULL |     NULL | 
+----------+----------+----------+
7 rows in set (0.00 sec)



mislim da dalje umes sam ...

[ bogdan.kecman @ 18.05.2009. 15:18 ] @
da, ako neces za samo jednog usera ..

Code:

mysql> SELECT k1.userid, k1.friendid, k2.friendid, k3.friendid FROM t_friend k1 LEFT JOIN t_friend k2 ON (k2.userid = k1.friendid) LEFT JOIN t_friend k3 ON (k3.userid = k2.friendid);
+--------+----------+----------+----------+
| userid | friendid | friendid | friendid |
+--------+----------+----------+----------+
|      1 |        2 |        3 |        4 | 
|      1 |        2 |        3 |        7 | 
|      1 |        2 |        5 |     NULL | 
|      1 |        2 |        6 |     NULL | 
|      1 |        3 |        4 |     NULL | 
|      1 |        3 |        7 |     NULL | 
|      1 |        5 |     NULL |     NULL | 
|      2 |        3 |        4 |     NULL | 
|      2 |        3 |        7 |     NULL | 
|      2 |        5 |     NULL |     NULL | 
|      2 |        6 |     NULL |     NULL | 
|      3 |        4 |     NULL |     NULL | 
|      3 |        7 |     NULL |     NULL | 
+--------+----------+----------+----------+
13 rows in set (0.00 sec)


to sad sve moze verovatno jos malo da se optimizuje .. ovako sam cukao realtime po klijentu :)
[ fatality1 @ 18.05.2009. 16:04 ] @
prvo , hvala velika na odgovoru , ovako nesta mi i treba :)

a jos jedno pitanje , vidim da ti veze nisi snimao dva puta , npr. kod mene ako su user 1 i user 2 prijatelji imam dva unosa u t_friend tabeli (jedan gdje je user 1 friend , a drugi kada je user 2 friend) , i onda kod ovih upita gore dobijem malo izmiksane rezultate , tj. evo vidim desi se da ako krenem od user 1 , i trazim njegove prijatelje nekad nadje i sebe (jer dodje do user 2 a posto je i on prijatelj sa user 1 izbaci mi i to kao rjesenje) , i tu bih te htio pitat ima li nekakav drugi nacin da rijesim ove veze ili ih pak moram sve duplo unositi
[ bogdan.kecman @ 18.05.2009. 16:44 ] @
pogledaj malo po netu, sigurno ima resenje sa malo vise "razmisljanja" .. ovo sada je vec "budzenje" :)

Code:

mysql> SELECT k1.userid, k1.friendid, k2.friendid, k3.friendid FROM t_friend k1 
    -> LEFT JOIN t_friend k2 ON (k2.userid = k1.friendid or k2.friendid = k1.userid) 
    -> LEFT JOIN t_friend k3 ON (k3.userid = k2.friendid or k3.friendid = k2.userid);
+--------+----------+----------+----------+
| userid | friendid | friendid | friendid |
+--------+----------+----------+----------+
|      1 |        2 |        3 |        2 | 
|      1 |        2 |        3 |        4 | 
|      1 |        2 |        3 |        7 | 
|      1 |        2 |        5 |        2 | 
|      1 |        2 |        6 |        2 | 
|      1 |        3 |        4 |        3 | 
|      1 |        3 |        4 |        3 | 
|      1 |        3 |        7 |        3 | 
|      1 |        3 |        7 |        3 | 
|      1 |        5 |     NULL |     NULL | 
|      2 |        3 |        2 |        3 | 
|      2 |        3 |        2 |        5 | 
|      2 |        3 |        2 |        6 | 
|      2 |        3 |        4 |        3 | 
|      2 |        3 |        4 |        3 | 
|      2 |        3 |        7 |        3 | 
|      2 |        3 |        7 |        3 | 
|      2 |        5 |        2 |        3 | 
|      2 |        5 |        2 |        5 | 
|      2 |        5 |        2 |        6 | 
|      2 |        6 |        2 |        3 | 
|      2 |        6 |        2 |        5 | 
|      2 |        6 |        2 |        6 | 
|      3 |        4 |        3 |        4 | 
|      3 |        4 |        3 |        7 | 
|      3 |        4 |        3 |        2 | 
|      3 |        4 |        3 |        4 | 
|      3 |        4 |        3 |        7 | 
|      3 |        7 |        3 |        4 | 
|      3 |        7 |        3 |        7 | 
|      3 |        7 |        3 |        2 | 
|      3 |        7 |        3 |        4 | 
|      3 |        7 |        3 |        7 | 
+--------+----------+----------+----------+
33 rows in set (0.00 sec)


ali generalno, sada su (1,2) i (2,1) isti .. tj ako pera zna miku to znaci da i mika zna peru (ne bas uvek tacno u realnom zivotu...)
[ fatality1 @ 18.05.2009. 16:53 ] @
e bas to kod tebe u prvom redu sto stoji , znaci 1-2-3-2 , to cu jos malo pokusat optimirat , da mi ne izbacuje dva puta isti ID , vjerovatno cu pogled toga moci nesta i u javi odraditi , tj. nakon sto ucitam ovaj query
[ bogdan.kecman @ 18.05.2009. 23:09 ] @
iskreno ne znam kako bih ga ja radio ... dal bi samo citao iz baze raw data pa slagao graf u hl jeziku ili vadio neki stat iz mysql-a direktno ... koristio neke stored procedures ili udf-ove ... ovako na jedan, iz konzole sam nacukao sta je bilo "najjednostavnije" .. neko "najoptimalnije" resenje bi zahtevalo malo vise truda, ali verujem da imas dovoljno za pocetak :) ipak je to tvoj zadatak :D