NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Přátelství

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Martin Štěpánek :13.12.2015 16:22

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
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
katrincsak
Člen
Avatar
Odpovídá na Martin Štěpánek
katrincsak:14.12.2015 20:14

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:14.12.2015 20:18

Databází jsem myslel tabulku. **

 
Nahoru Odpovědět
14.12.2015 20:18
Avatar
Odpovídá na katrincsak
Neaktivní uživatel:14.12.2015 20:32

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
14.12.2015 20:32
Neaktivní uživatelský účet
Avatar
katrincsak
Člen
Avatar
Odpovídá na Neaktivní uživatel
katrincsak:14.12.2015 22:06

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
Tukmak:15.12.2015 0:33

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
Tukmak
Člen
Avatar
Avatar
posvicmichal
Člen
Avatar
posvicmichal:15.12.2015 0:52

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
Odpovídá na Martin Štěpánek
Neaktivní uživatel:15.12.2015 1:04

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
Neaktivní uživatelský účet
Avatar
Odpovídá na Neaktivní uživatel
Neaktivní uživatel:15.12.2015 1:06

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
Neaktivní uživatelský účet
Avatar
hitzoR
Člen
Avatar
Odpovídá na Tukmak
hitzoR:15.12.2015 7:13

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

Martin Štěpánek 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 :15.12.2015 13:27

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

Nahoru Odpovědět
15.12.2015 13:27
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
Odpovídá na hitzoR
Martin Štěpánek :15.12.2015 15:49

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
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
posvicmichal
Člen
Avatar
Odpovídá na Martin Štěpánek
posvicmichal:15.12.2015 19:31

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
15.12.2015 19:31
Avatar
Jan Lupčík
Tvůrce
Avatar
Odpovídá na posvicmichal
Jan Lupčík:15.12.2015 19:34
  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
15.12.2015 19:34
TruckersMP vývojář
Avatar
Odpovídá na posvicmichal
Neaktivní uživatel:15.12.2015 19:39

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
Neaktivní uživatelský účet
Avatar
posvicmichal
Člen
Avatar
Odpovídá na Jan Lupčík
posvicmichal:15.12.2015 19:39

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
hitzoR:15.12.2015 19:41

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 :15.12.2015 20:00

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
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
Michal Žůrek - misaz:15.12.2015 21:42

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í
+2,50 Kč
Řešení problému
 
Nahoru Odpovědět
15.12.2015 21:42
Avatar
Odpovídá na Michal Žůrek - misaz
Michal Žůrek - misaz:15.12.2015 21:47

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
Avatar
Michal Žůrek - misaz:15.12.2015 21:48

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

 
Nahoru Odpovědět
15.12.2015 21:48
Avatar
Odpovídá na Michal Žůrek - misaz
Martin Štěpánek :16.12.2015 20:31

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
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
Odpovídá na Martin Štěpánek
Michal Žůrek - misaz:16.12.2015 20:50

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
16.12.2015 20:50
Avatar
Odpovídá na Michal Žůrek - misaz
Martin Štěpánek :16.12.2015 21:00

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
Všechno jde naprogramovat, chce to jen čas a chuť...
Avatar
Odpovídá na Martin Štěpánek
Michal Žůrek - misaz:16.12.2015 21:10

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
16.12.2015 21:10
Avatar
katrincsak
Člen
Avatar
Odpovídá na Michal Žůrek - misaz
katrincsak:17.12.2015 9:16

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:23.12.2015 22:41

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