Diskuze: Pomoc s JOINom
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Tvůrce

Zobrazeno 36 zpráv z 36.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
Toto jsem dělal v prváku (2 roky zpět) při programování něčeho podobného. Ale tento postup je špatně. Ano jde to, ale tento postup se používá jednou za delší čas, jelikož je nároční na výpočet a bla bla bla. Já ti doporučuji si vytvořit vždy napojení na jednu tabulku v cyklu a tom bude další cyklus na napojení k další tabulce. Je to standardní postup.
S tím že to není ideální řešení souhlasím. Ale query v cyklu taky není úplně OK.. Nacpal bych id a názvy do array a pak přiřazoval.
Ahoj, join má základní syntaxi:
JOIN nazev_tabulky USING (pk_pro_spojeni)
Slovy řečeno připojuješ tabulku pomocí primárního klíče. V tvém případě by to mohlo vypadat takto:
SELECT nazev, popis, inzeraty.id_mesta, inzeraty.id_regionu, nazev_mesta, nazev_regionu FROM inzeraty
JOIN regiony USING(inzeraty.id_regionu)
JOIN mesta USING(inzeraty.id_mesta)
WHERE nejaka_podminka
Zkus něco takovýho
<?php
$inzeraty = $db->fetchAll("
SELECT `inzerat`.`id`, `inzerat`.`nazev` AS nazevInzeratu, `inzerat`.`popis`,
`mesto`.`nazev` AS nazevMesta,
`region`.`nazev` AS nazevRegionu
FROM `inzerat`
INNER JOIN `mesto` ON `inzerat`.`mestoId` = `mesto`.`id`
INNER JOIN `region` ON `inzerat`.`regionId` = `region`.`id`
");
foreach ($inzeraty as $inzerat) {
echo "Inzerát: {$inzerat->nazevInzeratu}, Město: {$inzerat->nazevMesta}, Region: {$inzerat->nazevRegionu}<br />";
}
Dávat jeden query na inzeráty a pak v cyklu další dva dotazy pro město a region není dobrej nápad, protože tím pak posíláš velké množství dotazů do DB.
pavelco, práve to je ten problém, že teraz to mám riešené cez 1 query
na vytiahnutie poľa inzerátov, a potom mám foreach na všetky tieto inzeráty
a pri každom cykle sa mi vykoná 5 query do databázy, a došli mi že to nie
je správna cesta
vypísanie 3 skúšobných inzerátov síce funguje super, vygenerovanie
stránky ma stojí 650ms, čo nie je pri 3 inzerátoch ani trošičku v poriadku
:/
Všetkým moc ďakujem za pomoc, ale pre úplnosť doplním: každý inzerát má id mesta, regionu, kategorie, podkategorie, inzerenta. Tieto 5 id sa musia nahradiť názvami. Je v poriadku pre databázu mať taký 5+ násobný join? jedná sa o postgres db. Ak to nie je v pohode, asi to spravím ako radil Richard (Nacpal bych id a názvy do array a pak přiřazoval.)
Pokud máš velkou databázi, tak proč by to nemělo být v pořádku? Select, kde je 5× join je mnohem efektivnější než 5× samotný select.
Pokud si o tom chceš přečíst něco víc, stačí googlit (https://www.google.cz/search?…)
Nevím, jaké přesně JOINy mají nevýhody, ale mám pocit, že přesně kvůli takovýmto případům se vytvářely. Koukal jsem na pár článků a diskusí a prakticky všude se psalo, že použití JOINů je lepší, než posílat několikanásobně víc dotazů (byť jednoduchých).
Když ony ty joiny sou takový zvěrstvo.. Pokud se využijí pole, ta data se budou moci dále použít, asi je to jen moje antipatie k joinům.
Postup bych si představoval asi takto: cyklem najít inzeráty, v každém cyklu zapsat do proměnné další where klauzoli, která se pak použije v sql dotazu (vím, blbej způsob, ale pro tu myšlenku to stačí a ušetří to spoustu dat) a samotná data z tabulky zapsat do pole. Po projetí vybrat data z ostatních tabulek, nacpat do pole k původním datům ta další a pak jen vypsat.
V některých případech bude i tento způsob o něco rychlejší, ikdyž uznávám že zápis je delší. Víc výhod má zřejmě join, pokud s nimi nemáš problém, použij join.
to asi ne, pretože by to chcelo 6 selectov za sebou
a potom prehnať 1. zoznam foreachom a nahradiť idčka podľa 2. až 6. zoznamu
kde to join spraví všetko za mňa a rovno vypľuje to čo chcem (teda
aspoň tak si to predstavujem ). ten join bude asi najrozumnejší, tak ho skusím, a ak bude trvať
kratšie než to trvá teraz, tak už toto bude podľa mňa výhra
To máš někde chybu, pár joinů v selectu je naprosto v pořádku a uvědom si, že joinuješ podle primárního klíče, tohle je dost rychlé a používá se to běžně. Hlavně tam nevymýšlej žádné cykly.
Však píšu ať použiješ join, pro tenhle případ lepší volba.
Zcela jistě ti můžu říct, že použití JOINu bude vždycky rychlejší, než použití cyklů a několika SELECTů. Ale je otázka, k čemu se ty konkrétní způsoby použijí. Když budu potřebovat v jednom řádku výpisu mít více hodnot z jiné tabulky, tak to JOINem nepůjde a musí se použít cykly. Pokud však jde o pouhé nahrazení identifikátorů jménem (z číselníku), pak je JOIN naprosto nejlepší volbou.
Pokud jde o jednoduché zadání jako zde tak ano, protože těch dat bude pár a na jednom místě, budou se jednorázově používat, nic dalšího ani složitějšího se s tim dělat nebude. Jsem asi už deformovanej, u nás joiny prostě použít nemůžeme, proto je podvědomě odkládám na druhou kolej.
Chci tím říct, že ikdyž je join mnohdy rychlejší, ne vždy je to spása.
A kde pracuješ? To mi přijde jako nesmysl, JOINY potřebuješ ať chceš nebo ne a zanášet výběr dat do logické vrstvy je hodně špatný nápad, k tomu ta databáze je.
Analýza statistických dat + big data.
Pokud vypisuješ pár dat z databáze, tak ti to stačí, ale pokud s těmi daty
potřebuješ pracovat, tisíckrát třídit, porovnávat, pokud potřebuješ z
jedný tabulky mnoho sad dat podle určitých parametrů, budeš mít buďto
10000 query s joinama, a stejně to budeš zpracovávat, akorát blbějc, nebo
několik jednotek jendoduchých query a budeš mít k dispozici kompletní sady
dat.
Uznávám že doporučovat tady něco jinýho než join byl fail, ale mnohem větší fail je tvrdit že bez joinu se člověk nikdy neobejde, nehledě na druhou část tý věty.
Neber to jako útok, naopak tě opravdu uznávám, ale pokud s něčím nemáš zkušenosti, nemůžeš tvrdit že to funguje jednotně všude a že všude je ten nebo onen způsob správný.
Jestli s těmi daty děláš další složité výpočty, tak na to databáze moc není, tomu bych věřil. Nějak se mi ale nechce věřit tomu, že bys takhle jednoduchý problém jako řeší autor dotazu urychlil v aplikaci a i kdyby ano, tak on nikdy nedosáhne takového počtu dat, aby se tím vůbec vyplatilo zabývat. S tímhle mám zas zkušenosti já, máme očividně odlišné světy a zde řešený problém přijde blíže tomu mému, protože těch inzerátů asi nemá miliony.
Tak ani jeden netušíme kolik dat bude nebo co s tím dál bude dělat (jo,
nejspíš pár a vypíše to, ale co kdyby ), ale uznal jsem že join je
určitě lepší volba a že doporučovat něco jiného byl fail.
len tak pre zaujímavosť:
pomocou obyčajného selectu bez joinov získať zoznam 3 vyhovujúcich
inzerátov, a následne foreach cez tieto inzeráty kde sa pri každom volali
ďalšie 2 selecty aby sa namiesto id mesta a id regionu nahradili názvy miest
a názvy regionov... 320-350ms
pomocou selectu s dvoma jednoduchými joinami kde mi namiesto id mesta a id regionu doplnila názvy miest a názvy regionov databáza... 180-220ms
a to ide len o 3 inzeráty
čo by to s tým foreachom a ďaľšími selectami bolo, keby ich tam bolo 100
možno to neskôr
vyskúšam
pomohol som si s riešením ktoré tu dal Martin Konečný (pavelco1998), to od
Tukmaka mi na Postgrese 9.0 nefunguje
Heh děkuji za označení.
Btw, jedno příliš nepobírám - jak může tak jednoduchý SQL dotaz
zabít tolik času?
Že se mi aplikace v Nette na localhostu načítá asi 1000ms, to je ještě v
poho (EXPLAIN SQL dotazu je většinou kolem 0.0003s), ale jeden query
200ms?
Jasně, asi jsem se zapomněl zmínit... USING je zkratka pro JOIN ON, ale dá se použít jen za předpokladu, že sloupce v obou tabulkách, přes které tabulky spojuješ, mají stejné jméno.
ja si schválne dávam názvy v tabuľkách takto: inzety - inzerat_id,
inzerat_nazov... a to z toho dôvodu, že raz budem používať joiny, tak aby
som sa na 1000% niekde nepomýlil, a ak potrebujem tak si ich cez inzerat_id
AS id premenujem nikdy
som však joiny nepotreboval, tak som úplne zabudol ako ich používať
zatiaľ mi takéto pomenovanie
tabuliek a atributov vyhovuje, no možno to zmením ak na to bude dobrý
dôvod
No pôvodne som to robil takto:
ten 2. krok pozostával z opakovania týchto krokov:
pri 3 inzerátoch to máme 1 + 3*9 selectov a to bol problém,
pre ktorý som toto vlákno zakladal
teraz mám všetko v jednom selecte :3
ešte jeden postreh: predtým mi výpis nednoho inzerátu trval 550-600ms,
teraz 80-100ms takže joiny
vedieť je veľmi výhodné, aj napriek tomu že mám v jednom selecte 8 joinov
Obvykle i ty SELECTy by měly být rychlé, když jsou jednoduché a hledáš podle primárního klíče. Nicméně ty JOINy se mi zdají pro tento účel lepší a zároveň snazší na použití (prostě máš všechna data ihned pohromadě).
Já mám v jednom query dotazu 11 joinů (9x LEFT, 2x INNER) a dle EXPLAIN v tom není žádný problém.
Mohol by si mi prosím ešte v rýchlosti vysvetliť rozdiely a použitie
INNER a OUTER, LEFT a RIGHT joinov prosím? ja už musím ísť spať tak si to
zajtra pozriem, ak teda máš na to času
http://stackoverflow.com/…nd-full-join
Nechce se mi to moc slovně popisovat, protože bych ti určitě napsal něco
špatně.
Jakože vím, v jakém případě jaký použít, ale kdybych ti to měl napsat,
tak bych se v tom možná trochu zamotal.
To je pravda sú tam pekné
grafy, ďakujem
Jojo v poho. Osobně jsem třeba RIGHT JOIN použil snad jen jednou za život, OUTER nebo CROSS nikdy. Nejvíc se využije INNER a LEFT.
Já OUTER používám poměrně často. Když zobrazuju ve své aplikaci detail požadavku, tak ve stavu NOVÝ ještě není v DB vyplněn "řešitel", "datum řešení" apod. Abych nemusel pro každý stav požadavku dělat extra zobrazení, udělám jen jedno a při použití OUTER se mi prostě jen ty prázdné údaje nezobrazí. Kdybych použil INNER nezobrazí se vůbec nic, protože INNER vyžaduje vyplněné všechny vybírané položky...
Pokud jsem tvůj případ pochopil dobře, pak to obvykle řeším LEFT
JOINem, kdy z druhé tabulky dostanu NULL.
Je ale pravda, že OUTER moc neznám a je možné, že by se mi v některých
případech hodil líp.
Díky
Levý a pravý JOIN je vždy OUTER INNER je ten výchozí.
Jak píše David Hartinger , když napíšeš LEFT JOIN, tak jsi použil LEFT OUTER JOIN. LEFT nebo RIGHT určuje pouze stranu dotazu, na které se mohou vyskytovat prázdné položky...
Zajímavá čísla, ještě jsem to rozšířil (měřeno na desktopu, takže nic přesného, průměr z 5 opakování):
Query s joinem: 0.0018 s
Query a v cyklu query na zjištění názvů měst a regionů: 0.0041
s
Query na inzeráty, data o městech a regionech (3x query), všechno nacpáno do
polí a následně přiřazeno: 0.0023 s
To všechno s téměř s prázdnou tabulkou (3 inzeráty, 3 regiony, 3
města).
Pokud záznamy začnou přibývat, query s joinem nemá problém, druhá
možnost se extrémně zpomaluje, a třetí možnost jen mírně (kvůli
procházení větším polem).
PS. Na čem si to měřil, že to tomu hw trvalo tak dlouho?
Moj testovaci apache pod win 7 (lokalne), a db postgres 9 na serveroch
websupportu (nie lokalne). Taktiez niesu to len dotazy ale komplet system s
generovanim sablon, routovanim atd, napisal som sam, malinko podobne tomu z
tutorialov (dalsi projekt bude snad na nette alebo laraveli z dovodu, ze sa mi
uz nechce riesit kazdu prkotinu ktora uz vyriesena je). Casy su podla toho za
kolko ho chrome dostane vygenerovane naspat. Net je Slovenska akademicka siet.
Raz som pouzival aj pocitadlo v php ale oproti casom v chrome to bolo par ms
rozdiel, tak to snad aspon trochu spolahlive bude tie joiny su skvela vec, lebo
som okrem casu usetril aj zbytocny kod
Na takováto mereni pozor, DB si děla nejake cache, takže když tu query
spustis poprvé, většinou tvá jinak dlouho než podruhé a další případy
jsou také mnohem rychlejší. Merit bys mel na dostatecnych datech, na 3
polozkach se nepozná nic a může to zpomalovat třeba i samotné parsovani
toho příkazu Jestli mas
chuť, vygeneruj tam par tisíc položek a hod sem casy, to uz bude
zajímavé.
David Hartinger, Michal Štěpánek: No vidíte, vím jak to použít, ale ani
nevím, jak přesně se to jmenuje Děkuji za doplnění.
Zobrazeno 36 zpráv z 36.