Autor | Zpráva | ||
---|---|---|---|
Jcas Profil * |
#1 · Zasláno: 28. 5. 2014, 21:07:17
Použiji takovou svou terminologii:
Levá tabulka(LT) JOIN pravá tabulka(PT) (nalevo od JOIN a napravo od JOIN) 1. Příklad 1 V levé tabulce (Petr, Pavel) jsou 2 záznamy. V pravé je jich 4 (kouří, pije, zahýbá, krade). Petr - kouří, pije, krade Pavel - pouze zahýbá. Vyber vše z `LT` JOIN `PT` - vrátí pouze 2 záznamy, s tím že Petrovi přiřadí první nalezenou hodnotu. ( vlevé tabulce jsou pouze 2 hodnoty) A když to zrcadlově prohodím. LT za PT (vybírám 4 řádky z tabulky a k nim přiřadím jméno), tak výsledkem budou 4 hodnoty a tím získám potřebný výsledek. Petr - kouří, pije, krade a Pavel - pouze zahýbá. 2. Příklad Nyní schválně vynechám hodnoty NULL. Vyber vše z `LT` LEFT JOIN `PT` -vrátí 4 hodnoty. Pokud v pravé tabulce existuje více záznamů, tak se vyberou také. Hodnota z levé tabulky se zopakuje. Tedy: -Petr - kouří -Petr - pije -Petr - krade -Petr - zahýbá 3. Příklad Ty nuly asi chápu dobře. Pokud do levé tabulky přidáme Michala, který je naprosto slušný, Tak výsledkem bude 5 řádků. A ten 5. bude. - Michal - null 4. Příklad - Spojení více jak dvou tabulek. Vytvoříme třetí tabulku `co`. Krade (auta, prachy), pije (pivo, vodu), zahýbá (za roh), kouří (trávu) Našel jsem syntaxi, Která je: JOIN....ON.... JOIN....ON.... JOIN....ON.... Při vytahování dat se používá while , kdy dotaz vrátí záznam a pak se snaží najít další, když ho najde, tak cyklus while pokračuje, když ne, tak se ukončí.
Lze tedy říci, že toto napojení JOIN na sebe se chová stejně jako while? While(je vrácen záznam){ //Petr pije, při dalším průběhu cyklu Petr - krade, a při 3. kouří while(je vrácen záznam) { //pije pivo - při druhém průběhu - pije vodu, a při 3. trávu while(je další záznam) { //kdybych přidal další tabulku - pivo-bernard } } } A jak postupně nenachází záznamy, tak jeden cyklus za druhým končí. Co mi ale není jasné, je podmínka WHERE na konci. ta se musí stahovat na všechny JOIN? Nebo se vztahuje pouze k prvnímu? |
||
Kcko Profil |
Jcas:
Sorry, nemám část tvůj sloh, ale vizuálně Ti pomůže tento obrázek |
||
Alphard Profil |
#3 · Zasláno: 28. 5. 2014, 21:54:48
K tomu
where , aplikuje se na spojení všech tabulek, kdy (před vyfiltrováním v klauzuli join on ) vzniká kartézský součin – tedy vzájemné kombinace všech záznamů ve spojovaných tabulkách. Takže se běžné kombinují sloupce různých tabulek where tabA.sloupec = 1 and tabB.sloupec = 2 .
Snad jste se ptal na tohle, nejsem si z toho dotazu úplně jistý. |
||
juriad Profil |
A co kdyby sis to zkusil? http://sqlfiddle.com/#!2/cc21d/4
JOIN vždy porovná každou hodnotu v první tabulce s každou hodnotou v druhé tabulce a ponechá jen takové záznamy, které splňují vazební podmínku. Z toho vyplývá, že JOIN je nezávislý na pořadí tabulek. Nic jako „vybere první“ v SQL neexistuje (podle standardu), k tomu bys musel použít nějakou agregační funkci. Dotaz vždy vybere všechny možnosti, které splňují podmínky. Tedy 1. příklad vrátí v každém případě 4 záznamy. Pokud použiješ LEFT JOIN či RIGHT JOIN, tam už závisí na pořádí tabulek. Doporučuji vždy používat LEFT JOIN a na variantu RIGHT zapomenout. Jak jsem povídal, že databáze zkusí porovnat každý s každým, tak v případě LEFT JOINu, pokud pro záznam v levé tabulce nenalezne žádný záznam v pravé, přesto jej vrátí (sloupce odpovídající těm z pravé tabulky budou NULL). Tedy 2. příklad se bude chovat úplně stejně jako 1, protože pro každého člověka existuje alespoň jedna neřest. 3. příklad Ale pokud bys přidal Michala, který nemá žádnou neřest, tak by jej dotaz s JOINem nevrátil vůbec (neexistuje neřest, kterou by měl), ale dotaz s LEFT JOINem ano (neřest je nahrazena NULLy). Jelikož přílíš nezáleží na pořadí JOINovaných tabulek, je logické, že je můžeš JOINovat, jak se ti zlíbí. Pokud začneš používat LEFT JOIN, na pořadí začne záležet, ale stále si jakoby můžeš JOINy uzávorkovat jak chceš (operace je asociativní). Kdysi dávno JOIN neexistoval a vše se dělalo jen pomocí čárky (má význam spojení všeho se vším): SELECT * FROM leva, prava WHERE leva.col1 = prava.col2 AND leva.col3 = 42 Pak se přišlo na to, že se v podmínce WHERE motají podmínky dvou typů: 1) podmínka na vazbu (co musí platit mezi tabulkami) 2) podmínka na filtrovanou hodnotu (podmínka s konstantou) Může se zdát, že podmínek je málo, ale v praxi se ti jich může sejít třeba deset. Proto se navrhl systém JOINů, aby se dotaz zpřehlednil: SELECT * FROM leva JOIN prava ON leva.col1 = prava.col2 WHERE leva.col3 = 42 Jak jsem ukázal na příkladu v sqlfidlu, i v tom jednoduchém příkladě potřebuješ tři tabulky, protože člověk může mít více neřestí a naopak jednu neřest může mít více lidí. Jde o vztah M-ku-N. Pokud bys chtěl přidat další vlastnost co (co-pije, co-krade, ...), tak jde o ternární vazbu (ta prostřední tabulka se odkazuje na tři tabulky, nikoli jen na dvě). Ale to vůbec nic nemění na tom, že prostě přidáš ještě jeden JOIN. V klauzuli FROM může být libovolné množství tabulek propojených JOINem, klauzule WHERE se týká filtrování. Pokud bys chtěl nějaký netriviální příklad s více JOINy, tak zkus najít dvojici lidí, kteří mají stejnou neřest a zároveň jeden z nich kouří (poslední část bude zvýrazněná). SELECT u1.name name1, u2.name name2, h.habit FROM users u1 JOIN user_habits uh1 ON u1.id = uh1.user_id JOIN user_habits uh2 ON uh1.habit_id = uh2.habit_id JOIN users u2 ON uh2.user_id = u2.id JOIN habits h ON uh1.habit_id = h.id # nebo ekvivalentně uh2.habit_id = h.id JOIN uh3 ON u1.id = uh3.user_id WHERE uh3.habit_id = 1 # alternativně: JOIN habits h2 ON h2.id = uh3.habit_id WHERE h2.habit = 'kouří' V tom dotazu name1, name2, uh1, uh2, u1, u2, h jsou aliasy (pojmenování sloupce či tabulky, aby se autor neupsal k smrti). Volitelně je před ně možné napsat AS:
SELECT u1.name AS name1 ... FROM users1 AS u1 |
||
Časová prodleva: 10 let
|
0