Diskuze: Přátelství

PHP PHP Přátelství American English version English version

Avatar
Martin Štěpánek (Enormyk):

Ahoj,
pracuji na jedné webové aplikaci, která je částečně sociální síť. Přátelství v ní funguje stejně jako tady nebo na wattpadu.
Tedy, že můžete odebírat uživatele a když se někdo navzájem odebírá, stanou se přáteli.
Mám klasickou tabulku odebírání kde je pět sloupců.
id_odebirani, id_kdo, nick_kdo, id_koho, nick_koho
Potřebuji nějaký SQL dotaz nebo php script, který mně získá výpis uživatelů, kteří se odebírají navzájem. Jediné co mě napadlo je projít všechny kombinace jenže to by bylo velmi náročné na server.
Předem moc děkuji za pomoc. :-)

Odpovědět 13.12.2015 16:22
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
katrincsak
Člen
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
katrincsak:

Napadli mě 2 možnosti, ale dlouho jsme nepřemýšlel a tak možná budou i lepší řešení.

  1. Vytvoř si další databázi, odberatele a ukládej ID odběratele a odebíraného.. Takže Víš kdo koho.. Pak už jen hodíš dotaz kdo a vypíšeš si pole.
  2. Vytvoř si sloupec a ukládej si do něj v řetězci ID odebíraných.. např. 5,20,1,600 a výsledně je to stejné, jen horší manipulace, ale za pomocí funkce např
$pole[]  = explode(",",$sloupec);

si vytvoříš pole ale, musíš vytvářet další dotaz na výpis uživatelů dle id, stejně tak v příkladu 1.

Nejlepší řešení dle mě je příklad 1, kde si doplníš do DB vše co se toho týká joineš to s uživatelem a máš to jako 1 dotaz a kdykoliv ;-)

 
Nahoru Odpovědět 14.12.2015 20:14
Avatar
katrincsak
Člen
Avatar
katrincsak:

Databází jsem myslel tabulku. **

 
Nahoru Odpovědět 14.12.2015 20:18
Avatar
Inoue Yūki
Redaktor
Avatar
Odpovídá na katrincsak
Inoue Yūki:

Mám takový dojem, že tuhle vazbu má vyřešenou. Jestli jsem dotaz pochopil správně, tak by chtěl dotazem vrátit uživatele, kteří se navzájem odebírají právě z tabulky odběratele, kterou popsal v dotazu. Je to tak?

Nahoru Odpovědět  +1 14.12.2015 20:32
Avatar
katrincsak
Člen
Avatar
Odpovídá na Inoue Yūki
katrincsak:

Pravda, prakticky jsem napsal to co již má a špatně pochopil dotaz.

Záleží k čemu to přesně potřebuje a jak to přesně potřebuje. K čemu je porovnávat vazbu mezi všemi odběrateli.
Ale pakliže potřebuji zjistit vazbu mezi všemi, tak je nutné se všech zeptat. nebo si postupně vytvářet evidenci.

Pakliže potřebuje zjistit společné odběratele mezi tím na koho se např. zrovna budu dívat, tak to je jednoduché a to předpokládám, že není ono. Protože pak je to porovnání jen 2 ID .

 
Nahoru Odpovědět 14.12.2015 22:06
Avatar
Tukmak
Člen
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
Tukmak:

Ahoj,

nějak mi to nedalo spát a tak jsem dal něco dohromady.

http://sqlfiddle.com/#…

Snad je to, co si chtěl :-) .

 
Nahoru Odpovědět 15.12.2015 0:33
Avatar
posvicmichal
Člen
Avatar
posvicmichal:

Jak chceš ty uživatele získat? Resp. jaký má být výstup? Podle toho, co píšeš, chceš z jedné tabulky dva výstupy, jak chceš ty výstupy potom porovnávat? :)

 
Nahoru Odpovědět 15.12.2015 0:52
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
Jiří Gracík:

A co mít tabulku, kde bude followId, aUserId, bUserId, aFollows, bFollows.

Uživatele budeš přidávat do tabulky, tak třeba ten s nižším id bude A, druhý B. No a pak jenom hodíš select where aFollows je true a bFollows je true.

Nahoru Odpovědět 15.12.2015 1:04
Creating websites is awesome till you see the result in another browser ...
Avatar
Jiří Gracík
Redaktor
Avatar
Odpovídá na Jiří Gracík
Jiří Gracík:

Začínám si uvědomovat, že tak moc šikovný to není. Ale jenom na to, co tady píšeš, by to bylo fajn :D :D

Nahoru Odpovědět 15.12.2015 1:06
Creating websites is awesome till you see the result in another browser ...
Avatar
hitzoR
Člen
Avatar
Odpovídá na Tukmak
hitzoR:

Takhle to fungovat nebude. Viz. http://sqlfiddle.com/#…

Martin Štěpánek (Enormyk) Ten návrh tabulky je špatně, stačí jenom id_kdo a id_koho, nic víc. Ani tam nemusíš mít žádné speciální ID jako primární, jednoduše použiješ kompozitní klíč. Pokud například potřebuješ získat všechny "přátele" na profilu konkrétního uživatele, tak to není zas tak těžké. Viz. upravená verze dotazu od Tukmak http://sqlfiddle.com/#… pro uživatele s ID 1. Pokud chceš kompletní výpis přátel, tak můžu během dneška něco vyzkoušet, mám v hlavě několik řešení, ale nevím jak moc jsou použitelné. :-D

 
Nahoru Odpovědět 15.12.2015 7:13
Avatar
Martin Štěpánek (Enormyk):

Ty nicky a Id tam mam jen abych nemusel spojovat tabulky. :-)

Nahoru Odpovědět 15.12.2015 13:27
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
Odpovídá na hitzoR
Martin Štěpánek (Enormyk):

Kdyby jsi byl tak hodný, byl bych ti vděčný. :-)
Potřebuji to tak, že když se budou dva lidé navzájem odebírat, stanou se přáteli. A já potřebuji, aby se každému uživateli po přihlášení vypsal seznam jeho přátel. Tedy vlastně nick_koho.

Nahoru Odpovědět 15.12.2015 15:49
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
posvicmichal
Člen
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
posvicmichal:

Nestačilo by tedy něco na způsob :

$query = mysql_query("SELECT * FROM odebirani WHERE id_koho = ".$idPrihlasenehoUzivatele);
while($odberatel = mysql_fetch_object($query){
        echo $odberatel->nick_kdo;
}

?

 
Nahoru Odpovědět  -2 15.12.2015 19:31
Avatar
IT Man
Redaktor
Avatar
Odpovídá na posvicmichal
IT Man:
  1. Kód je velmi nebezpečný - dosazuješ proměnnou do dotazu bez ošetření.
  2. mysql_query už je deprecated od verze 5.3 (zda-li se nepletu). V PHP 7 už je odebráno.
Nahoru Odpovědět  +2 15.12.2015 19:34
Když nevíš jak dál, podá ti ruku někdo, od koho by jsi to nečekal. A tu šanci musíš přijmout!
Avatar
Samuel Illo
Redaktor
Avatar
Odpovídá na posvicmichal
Samuel Illo :

Ovládač mysql sa už nemá používať, náhrada zaň je mysqli alebo ešte bezpečnejšie PDO

Nahoru Odpovědět 15.12.2015 19:39
www.samuelillo.com; lamka02sk(zavináč)samuelillo.com, www.point.samuelillo.com, www.csgorig.eu
Avatar
posvicmichal
Člen
Avatar
Odpovídá na IT Man
posvicmichal:

Však já vím, říkám něco na ten způsob. Spíše mi šlo o to, jestli dobře chápu, co vlastě chce.

 
Nahoru Odpovědět 15.12.2015 19:39
Avatar
hitzoR
Člen
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
hitzoR:

http://sqlfiddle.com/#… Tohle by mělo být přesně ono. V PHP pak akorát dosazuješ ID uživatele na do ON u prvního joinu místo 1.

 
Nahoru Odpovědět 15.12.2015 19:41
Avatar
Odpovídá na posvicmichal
Martin Štěpánek (Enormyk):

To nejde protože to vypíše jen ty co odebírá uživatel, ne ty, kteří se odebírají navzájem.

Nahoru Odpovědět 15.12.2015 20:00
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
Michal Žůrek (misaz):

jde to udělat hezky a jednoduše přes SQLko (aby se neřeklo, tak souhlasím s tím, že je to piplačka).

CREATE DATABASE pratelsky_spolek
  CHARACTER SET utf8
  COLLATE utf8_czech_ci;
USE pratelsky_spolek;

CREATE TABLE clovek (
  id INT NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (id),
  nick VARCHAR(255) NOT NULL
);

CREATE TABLE odberatel (
  odebiratel INT NOT NULL,
  odebirany  INT NOT NULL,
  PRIMARY KEY (odebiratel, odebirany),
  FOREIGN KEY (odebiratel) REFERENCES clovek (id)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  FOREIGN KEY (odebirany)  REFERENCES clovek (id)
    ON DELETE CASCADE
    ON UPDATE CASCADE
);

INSERT INTO clovek (nick) VALUES
  ('Karl'),
  ('Tom'),
  ('SweetCandy'),
  ('Strawberry'),
  ('World king');

INSERT INTO odberatel (odebiratel, odebirany) VALUES
  (1, 2), -- --------|
  (1, 4), -- --------+----|
  (2, 4), --         |    |
  (3, 2), -- --------+----+----|
  (2, 1), -- --------|    |    |
  (3, 1), --              |    |
  (4, 1), -- -------------|    |
  (3, 4), --                   |
  (4, 5), --                   |
  (2, 3); -- ------------------|

SELECT *
FROM odberatel as p
WHERE p.odebiratel = ? and p.odebirany IN
(
  SELECT odebiratel
  FROM odberatel
  WHERE odberatel.odebirany = ?
);

Nejpodstatnější je asi poslední SELECT, místo otazníku dej id uživatele, od kterého chceš dostat s kým se oboustranně přátelí.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět 15.12.2015 21:42
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Michal Žůrek (misaz):

pak si to samozřejmě můžeš vyšperkovat JOINem.

SELECT p2.nick AS odberatel, p1.nick as odebirany
FROM odberatel as p
JOIN clovek AS p1 ON p.odebirany = p1.id
JOIN clovek as p2 ON p.odebiratel = p2.id
WHERE p.odebiratel = ? and p.odebirany IN
(
  SELECT odebiratel
  FROM odberatel
  WHERE odberatel.odebirany = ?
);
Nahoru Odpovědět 15.12.2015 21:47
Nesnáším {}, proto se jim vyhýbám.
Avatar
Michal Žůrek (misaz):

Ad 2. Za otazníky musíš pro správnou funkčnost doplnit stejné ID.

Nahoru Odpovědět 15.12.2015 21:48
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Martin Štěpánek (Enormyk):

Vypadá to pro mě jako začátečníka v SQL šíleně, ale moc děkuji. :-)

Nahoru Odpovědět 16.12.2015 20:31
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
Michal Žůrek (misaz):

tak ty základní příkazy, CREATE TABLE, CREATE DATABASE, INSERT INTO, USE asi chápeš, možná cizí klíče při vytváření tabulky odberatel, ale kdybys je nenapsal, konec světa nenastane. Složitější je možná pak už jen ten select, který v podmínce ošetří aby to fungovalo oboustranně. V podstatě se jedná o to že to skontroluje pokud to funguje A => B a pak jestli A je na seznamu těch, které odebírá B. Čili A <==> B. Ten JOIN je vlastně to samé, jen to tam připojí nicky. Až to budeš používat ještě si sprav, že mi tam někde uniklo, že as a and jsou malými písmeny :)

Nahoru Odpovědět  +1 16.12.2015 20:50
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na Michal Žůrek (misaz)
Martin Štěpánek (Enormyk):

Super a můžeš mi ještě jen vysvětlit co dělá ten dotaz při vytváření tabulky odberatel? :-)

... FOREIGN KEY (odebiratel) REFERENCES clovek (id)
    ON DELETE CAS....
Nahoru Odpovědět 16.12.2015 21:00
Nesnáším, když někdo u if nepoužívá {}, byť se jedná o jeden řádek.
Avatar
Odpovídá na Martin Štěpánek (Enormyk)
Michal Žůrek (misaz):

ten nastavuje ty cizí klíče. V podstatě databázi řekne, že sloupeček odebiratel odkazuje do tabulky clovek na sloupeček id a databáze ti nedovolí tam vložit číslo, které není id nějakého člověka. Další dva řádky říkají, co se má stát, když dojde k smazání vázaného záznamu v tabulce clovek.CASCADE říká, že když řádek smažu, smaže se i v tabulce odebiratel (jinými slovy když smažu člověka, tak se smažou všechny záznamy odebíraní, kde je uveden). To samé platí pro změnu, když změním id uživatele na všech záznamech se změní.

V podstatě jde jen o to, že když bys tam v tomto okamžiku spustil příkaz

INSERT INTO odberatele (odberatel, odebirany) VALUES (1, 100)

tak ti to vyhodí chybu, protože nikdo s číslem 100 tam není. To ON UPDATE a ON DELETE je jen třešnička na dortu.

Nahoru Odpovědět  +2 16.12.2015 21:10
Nesnáším {}, proto se jim vyhýbám.
Avatar
katrincsak
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
katrincsak:

Elegantní řešení, krásná ukázka jak dobře pracuje MySQL a jak lze spoustu věcí udělat díky ní, aniž by člověk použil některé podmínky v php, nebo další dotazy. Opravdu pěkné !
Ale zdá se mi jinak, že jsem to prvně pochopil správně a jen si to napsal po svém, tedy s myšlenkou úplně stejnou, ale bez nějaké ukázky.

 
Nahoru Odpovědět 17.12.2015 9:16
Avatar
Pavel Jelínek:

Taky jsem si to zkusil vyřešit. Myslím, že jsem došel ke stejnému cíli trochu jinou cestou než misaz.
V zadání se píše "výpis uživatelů, kteří se odebírají navzájem":

Takže všechny tyto uživatele bych si z tabulky od misaz vytáhl takto:

SELECT p1.* FROM odberatel p1
WHERE p1.odebirany = (SELECT p2.odebiratel FROM odberatel p2 WHERE p2.odebirany = p1.odebiratel
AND p2.odebiratel = p1.odebirany)
AND p1.odebiratel < p1.odebirany

Pokud chci jednoho konkrétního uživatele, tak jako vyřešil misaz, upravím jen trochu podmínky:

SELECT p1.* FROM odberatel p1
WHERE p1.odebirany = (SELECT p2.odebiratel FROM odberatel p2 WHERE p2.odebirany = p1.odebiratel
AND p2.odebiratel = p1.odebirany)
AND p1.odebiratel =  ?

phpMyAdmin vrací výsledek mého dotazu a zanedbatelnou tisícinku rychleji.
Třeba při větší tabulce by už to tak zanedbatelné nebylo :-)

Jinak super web! Objevil jsem to tu nedávno. Zrovna se prokousávám tutoriály o OOP v PHP.

 
Nahoru Odpovědět  +1 23.12.2015 22:41
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 28 zpráv z 28.