Java týden Java týden
Pouze tento týden sleva až 80 % na celý Java e-learning!
Brno? Vypsali jsme pro vás nové termíny školení OOP v Brně!

Lekce 7 - MS-SQL krok za krokem: Dotazy přes více tabulek (JOIN)

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, MS-SQL krok za krokem: Datové typy a NULL, jsme si ukázali datové typy a vysvětlili hodnotu NULL. Dnes v MS-SQL tutoriálu začneme pracovat na jednoduchém redakčním systému, který může připomínat ten zde na ITnetwork. Ukážeme si dotazování přes více tabulek.

Konceptuální model

V následujících dílech si tedy v databázi vytvoříme takový zjednodušený ITnetwork. Pobavme se nejprve o tom, jak to bude vypadat. Dnes stihneme pochopitelně jen malou část. Protože obrázek někdy řekne více, než tisíc slov, začněme právě jím.

Konceptuální model redakčního systému

Co vidíte je tzv. konceptuální model. Je vytvořený pomocí notace (grafického jazyka) UML a v praxi se takovéto diagramy velmi často tvoří předtím, než začneme psát nějaký kód. Dobře si tak nejprve rozmyslíme, co že to vlastně chceme udělat.

Vidíme, že v systému figuruje uživatel, který může psát komentáře a články. Články spadají do sekcí. Jedná se tedy o databázi takového velmi jednoduchého redakčního systému, který si díky ITnetwork jistě dokážete představit.

Příprava tabulek a dat

Dnes se zaměříme na dotazy přes více tabulek. Pojďme si nejprve nějaké tabulky vytvořit. Bohatě nám budou stačit uživatelé a články.

Uživatelé

Protože uživatel bude vypadat trochu jinak, než nám vypadal doteď, založíme si tabulku Uzivatele znovu. Tu současnou tedy dropneme:

DROP TABLE [Uzivatele];

Následně vytvoříme tabulku novou. Uživatel zde bude mít (kromě Id) přezdívku, email a heslo:

CREATE TABLE [Uzivatele] (
        [Id] INT IDENTITY,
        [Prezdivka] NVARCHAR(155),
        [Email] NVARCHAR(155),
        [Heslo] NVARCHAR(255),
        PRIMARY KEY ([Id])
);

Pozn.: Může chvíli trvat, než se nová tabulka v Server Exploreru zobrazí.

Do uživatelů si rovnou nějaké vložíme:

INSERT INTO [Uzivatele] ([Prezdivka], [Email], [Heslo]) VALUES
('Míša', '[email protected]', 'dGg#@$DetA53d'),
('David', '[email protected]', '$#fdfgfHBKBKS'),
('Denny', '[email protected]', 'Jmls_aSW2RFss'),
('Ema', '[email protected]', 'fw8QT32qmcsld');

Články

Článek bude propojen s uživatelem, který ho napsal, tedy s jeho autorem. Tabulky propojíme tak, že do tabulky Clanky přidáme sloupec s Id autora. Tam bude hodnota Id uživatele (tedy primární klíč z tabulky Uzivatele), který článek napsal.

Hovoříme o vazbě 1:N (1 uživatel má N (několik) článků a každý článek patří právě jednomu uživateli). Část (zde článek) má vždy uložené Id celku (zde uživatel) kam patří.

Článek bude obsahovat (opět kromě svého Id) Id autora, krátký popis, url, klíčová slova, titulek, obsah a datum publikace. Založme si tabulku Clanky:

CREATE TABLE [Clanky](
        [Id] INT IDENTITY,
        [AutorId] INT,
        [Popis] NVARCHAR(155),
        [Url] NVARCHAR(155),
        [KlicovaSlova] NVARCHAR(155),
        [Titulek] NVARCHAR(155),
        [Obsah] NVARCHAR(MAX),
        [Publikovano] DATETIME,
        PRIMARY KEY ([Id])
);

Za povšimnutí stojí asi jen použití typu NVARCHAR(MAX) pro text článku.

Dále přidáme články a k nim přiřadíme uživatele jako autory. Vzal jsem 4 články zde z ITnetwork, které jsem značně zkrátil a zjednodušil. Dotaz bude následující:

INSERT INTO [Clanky] ([AutorId], [Popis], [Url], [KlicovaSlova], [Titulek], [Obsah], [Publikovano]) VALUES
(1, 'Co je to algoritmus? Pokud to nevíte, přečtěte si tento článek.', 'co-je-to-algoritmus', 'algoritmus, co je to, vysvětlení', 'Algoritmus', 'Když se bavíme o algoritmech, pojďme se tedy shodnout na tom, co ten algoritmus vůbec je. Jednoduše řečeno, algoritmus je návod k řešení nějakého problému. Když se na to podíváme z lidského pohledu, algoritmus by mohl být třeba návod, jak ráno vstát. I když to zní jednoduše, je to docela problém. Počítače jsou totiž stroje a ty nemyslí. Musíme tedy dopodrobna popsat všechny kroky algoritmu. Tím se dostáváme k první vlastnosti algoritmu - musí být elementární (skládat se z konečného počtu jednoduchých a snadno srozumitelných kroků, tedy příkazů). "Vstaň z postele" určitě není algoritmus. "Otevři oči, sundej peřinu, posaň se, dej nohy na zem a stoupni si" - to už zní docela podrobně a jednalo by se tedy o pravý algoritmus. My se však budeme pohybovat v IT, takže budeme řešit problémy jako seřaď prvky podle velikosti nebo vyhledej prvek podle jeho obsahu. To jsou totiž 2 základní úlohy, které počítače dělají nejčastěji a které je potřeba dokonale promýšlet a optimalizovat, aby trvaly co nejkratší dobu. Z dalších příkladů algoritmů mě napadá třeba vyřeš kvadratickou rovnici nebo vyřeš sudoku.', '2012-3-21'),
(2, 'Bakterie jsou obdoba buněčného automatu v kombinaci s hrou.', 'bakterie-bunecny-automat', 'bakterie, automat, algoritmus', 'Bakterie', 'Bakterie jsou obdoba buněčného automatu, který vymyslel britský matematik John Horton Conway v roce 1970. Celou tuto hru řídí čtyři jednoduchá pravidla:/n/n
1. Živá bakterie s méně, než dvěma živými sousedy umírá./n
2. Živá bakterie s více, než třemi živými sousedy umírá na přemnožení./n
3. Živá bakterie s dvoumi nebo třemi sousedy přežívá beze změny do další generace./n
4. Mrtvá bakterie, s přesně třemi živými sousedy, opět ožívá./n
Tyto zdánlivě naprosto primitivní pravidla dokáží za správného počátečního rozmístění bakterií vytvořit pochodující skupinky, shluky "vystřelující" pochodující pětice, překvapivě složité souměrné exploze, oscilátory (periodicky kmitající skupinky), či nekonečnou podívanou na to, jak složité a dokonalé obrazce dokáží tyto dvě podmínky vytvořit. Celý program je koncipován jako hra, máte za úkol vytvořit co nejdéle žijící kolonii. <a href="soubory/bakterie.zip" ', '2012-2-14'),
(3, 'Cheese Mouse je oddechová plošinovka.', 'cheese-mouse-oddechova-plosinovka', 'myš, sýr, hra', 'Cheese Mouse', 'Cheese mouse je plošinovka s "horkou ostrovní atmosférou", kde ovládáte myš a musíte se dostat k sýru. V tom vám ale brání nejrůznější nástrahy a nepřatelé jako hadi, krysy, pirane, ale i roboti, mumie a nejrůznější havěť. Hru s několika petrobarevnými světy jsem dělal ještě na základní škole s Veisenem a může se pochlubit 2. místem v Bonusweb game competition, kde vyhrála 5.000 Kč. Vznikala v Game makeru o letních prázdninách, ještě v bezstarostném dětství, což značně ovlivnilo její grafickou stránku. Rád si ji občas zahraji na odreagování a zlepšní nálady. <a href="soubory/cheesemouse.zip" />', '2004-6-22'),
(2, 'Pacman je remake kultovní hry.', 'pacman-remake', 'pacman, remake, pampuch, hra, zdarma', 'Pacman', 'Jedná se o naprosto základní verzi této hry s editorem levelů, takže si můžete vytvořit svá vlastní kola. Postupem času ji hodlám ještě trochu upravit a přidat nějaké nové prvky, fullscreen a lepší grafiku. Engine hry bude také základem mého nového projektu Geckon man, který je zatím ve fázi psaní scénáře. <a href="soubory/pacman.zip" />', '2011-6-3');

Dotazy přes více tabulek

Nyní máme v databázi články a k nim přiřazené uživatele. Pojďme si udělat dotaz přes tyto 2 tabulky, získejme články a k nim připojme přezdívky jejich uživatelů. Slovo připojme jsem nepoužil náhodou, příkaz pro spojení 2 tabulek se totiž jmenuje JOIN. Napišme si dotaz a poté si ho vysvětleme. Dotazy již budeme psát na více řádků, abychom se v tom vyznali.

SELECT [Titulek], [Prezdivka]
FROM [Clanky]
JOIN [Uzivatele] ON [Clanky].[AutorId] = [Uzivatele].[Id]
ORDER BY [Prezdivka];

Výsledek:

Titulek Prezdivka
Bakterie David
Pacman David
Cheese Mouse Denny
Algoritmus Míša

Na prvním řádku příkazu SELECT pracujeme se sloupci úplně stejně, jako kdyby byly v jedné tabulce, jednoduše vyjmenujeme, co nás zajímá. Jelikož vybíráme články a k nim připojujeme uživatele, budeme vybírat z tabulky Clanky. Připojení dat z jiné tabulky uděláme pomocí příkazu JOIN, kde uvedeme tabulku, kterou připojujeme, a poté klauzuli ON. Pokud mají v dvou tabulkách sloupce stejné názvy, předsadíme sloupec ještě názvem tabulky, do které patří a oddělíme tečkou. Klauzule ON je podobná jako WHERE, jen platí pro připojovanou tabulku a ne pro tu, ze které primárně vybíráme. V podmínce uvedeme, aby se ke každému článku připojil ten uživatel, jehož Id je uvedeno ve sloupci AutorId. Výsledek jsme seřadili podle přezdívky uživatelů. Kdybychom chtěli jen nějaké články, normálně bychom před ORDER BY uvedli ještě WHERE, jak jsme zvyklí.

INNER JOIN a OUTER JOIN

INNER (vnitřní) a OUTER (vnější) JOIN jsou 2 typy příkazu JOIN. Fungují úplně stejně, jediný rozdíl je v tom, co se stane, když položka, na kterou se vazba odkazuje, neexistuje.

INNER JOIN

Pokud uvedeme v SQL dotazu pouze JOIN, pokládá ho MS-SQL databáze za tzv. INNER JOIN. Pokud by v našem případě neexistoval uživatel s Id, které je u článku uvedeno, článek bez uživatele by vůbec nebyl ve výsledcích obsažen. Vazba je nerozdělitelná.

Pojďme si to zkusit, přidejme si článek, který bude odkazovat na Id neexistujícího uživatele:

INSERT INTO [Clanky] ([AutorId], [Popis], [Url], [KlicovaSlova], [Titulek], [Obsah], [Publikovano]) VALUES
(99, 'Článek s neexistujím uživatelem slouží pro vyzkoušení typů JOINů.', 'clanek-bez-autora', 'clanek, join, autor, chybejici', 'Článek bez autora', 'Tento článek je přiřazen neexistujícímu uživateli s ID 99 a slouží k vyzkoušení různých typů JOINů v MS-SQL databázi.', '2012-10-21');

Vložený článek se odkazuje na uživatele s Id 99, který v databázi není. Spusťme si nyní znovu náš SQL dotaz s JOINem. Pro přehlednost můžeme uvést, že chceme INNER JOIN.

SELECT [Titulek], [Prezdivka]
FROM [Clanky]
INNER JOIN [Uzivatele] ON [Clanky].[AutorId] = [Uzivatele].[Id]
ORDER BY [Prezdivka];

Výsledek:

Titulek Prezdivka
Bakterie David
Pacman David
Cheese Mouse Denny
Algoritmus Míša

Výsledek je stále stejný, článek bez autora mezi výsledky není.

LEFT OUTER JOIN

Vnější JOINy umožňují vybírat i ty výsledky, které se nepodařilo spojit z důvodu chybějících položek. Zkusme si tzv. LEFT JOIN, který výsledek uzná, pokud existuje levá část vazby (zde článek) a pravá (ta připojovaná, zde uživatel) neexistuje. Do hodnot sloupců z připojované části se vloží NULL.

SELECT [Titulek], [Prezdivka]
FROM [Clanky]
LEFT JOIN [Uzivatele] ON [Clanky].[AutorId] = [Uzivatele].[Id]
ORDER BY [Prezdivka];

Výsledek:

Titulek Prezdivka
Článek bez autora NULL
Bakterie David
Pacman David
Cheese Mouse Denny
Algoritmus Míša

Vidíme, že článek se stejně vybral, i když se nepodařilo vybrat pravou část (tedy tu připojovanou, uživatele). Před spojováním tabulek je dobré se zamyslet, zda nastane případ, kdy se spojení nepodaří a co v tom případě chceme dělat. U článku by se toto v reálu stát asi nemělo.

RIGHT OUTER JOIN

Podobně jako levý vnější JOIN uznal vazbu v případě, že levá část existovala, pravý JOIN to udělá naopak. Pokud bude existovat uživatel (pravá, připojovaná část) a nebude k němu existovat článek (levá část), bude stejně v tabulce zahrnut. Osobně jsem tento JOIN ještě nepoužil. V tabulce jednoho takového uživatele máme, je jím uživatel Ema. Zkusme si tedy RIGHT JOIN:

SELECT [Titulek], [Prezdivka]
FROM [Clanky]
RIGHT JOIN [Uzivatele] ON [Clanky].[AutorId] = [Uzivatele].[Id]
ORDER BY [Prezdivka];

Výsledek:

Titulek Prezdivka
Bakterie David
Pacman David
Cheese Mouse Denny
NULL Ema
Algoritmus Míša

Podle očekávání zmizel Článek bez autora a objevila se Ema.

Ještě nějaké JOINy bychom určitě v MS-SQL nalezli, ale pro naše účely nám toto bohatě stačí.

Wherování

Teoreticky se můžeme JOINům vyhýbat a používat místo nich jednoduše jen klauzuli FROM a WHERE. Ve FROM uvedeme více tabulek oddělených čárkami. Ve WHERE specifikujeme podmínku spojení tabulek. Databáze si v ideálním případě takovýto dotaz nejprve převede na INNER JOIN a poté jej zpracuje.

SELECT [Titulek], [Prezdivka]
FROM [Clanky], [Uzivatele]
WHERE [Clanky].[AutorId] = [Uzivatele].[Id]
ORDER BY [Prezdivka];

Výsledek je tedy stejný jako při INNER JOINu:

Titulek Prezdivka
Bakterie David
Pacman David
Cheese Mouse Denny
Algoritmus Míša

Nevýhoda wherování je, že tak neuděláme všechny JOINy a v určitých případech mohou být dotazy méně optimalizované. Nikdy nevíme, jak dotaz databáze optimalizuje a optimalizace se bude lišit podle typu databáze. Tento způsob berte spíše jako zajímavost a nepoužívejte ho.

V příští lekci, MS-SQL krok za krokem: Další dotazy a vazba M:N, budeme pokračovat v dotazech přes více tabulek a přidáme si do naší databáze další část redakčního systému.


 

 

Článek pro vás napsal Michal Žůrek - misaz
Avatar
Jak se ti líbí článek?
18 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Předchozí článek
MS-SQL krok za krokem: Datové typy a NULL
Všechny články v sekci
MS-SQL databáze krok za krokem
Miniatura
Následující článek
MS-SQL krok za krokem: Další dotazy a vazba M:N
Aktivity (5)

 

 

Komentáře

Avatar
MrPabloz
Člen
Avatar
MrPabloz:14.4.2014 17:30

Nechápu jak může psát článek o takovém tématu nřkdo kdo je ještě na základce. Neumí to a snaží se napsat o tom článek. Tak třeba wherování, co to je za blbost, říká se tomu podmínka ;) další věc, dotaz přes více tabulek = spojování. Create table článek je taky špatně, chybí ti tam reference, outer join už dávno není, je jen Left nebo Right join a nebo pouze join. Vysvětlení spojení tabulek je taky blbost. Prostě první se to pořádně nauč a vystuduj aspon na střední než se pustíš do takových článků...

Odpovědět  -8 14.4.2014 17:30
Harmonie těla a duše, to je to, oč se snažím! :)
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovídá na MrPabloz
Zdeněk Pavlátka:14.4.2014 17:33

Takhle kritizuj články až napíšeš lepší ;)

Odpovědět 14.4.2014 17:33
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
Odpovídá na MrPabloz
Michal Žůrek - misaz:14.4.2014 17:36

všechen kód byl testovaný a funguje.

 
Odpovědět  +1 14.4.2014 17:36
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na MrPabloz
David Čápka:14.4.2014 17:39

Co jsi napsal je snůška nesmyslů, termíny jsou v pořádku. FYI článek jsem psal já na VŠ, Michal byl tak hodný, že ho portoval z MySQL i pro MS-SQL.

EDIT: Uživatele Pabloz z diskuze vykazuji a jeho další zprávy maži.

Editováno 14.4.2014 17:45
Odpovědět  +5 14.4.2014 17:39
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Ondřej Štorc:14.4.2014 17:47

Ony ty články projdou ještě kontrolou od David Čápka (možná i jiných)..

Odpovědět 14.4.2014 17:47
Život je příliš krátký na to, abychom bezpečně odebírali USB z počítače..
Avatar
Odpovídá na MrPabloz
Michal Štěpánek:14.4.2014 21:52

Už to nehul...

Odpovědět  +1 14.4.2014 21:52
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
turlogh
Člen
Avatar
Odpovídá na David Čápka
turlogh:25.4.2014 7:12

Po pravdě řečeno považuji část se spojováním tabulek přes where také za naprostou blbost. Z jednoho prostého důvodu. DB engine není zase tak moc chytrý, při klasickém selectu přes více tabulek prostě provede kartézský součin obsahu tabulek a pak na něm teprve provádí dotazy. U tabulek, které mívají milióny záznamů je to zabijácký. Proto právě vznikly joiny, kde DB engine napřed vybere záznamy z první tabulky a teprve poté k nim dohrává záznamy z tabulky druhé.
A pro šťouraly ... databáze programuji již přes 20 let (oracle, mssql, firebird) a spojit 2 tabulky bez joinnu bych si snad netroufnul ani na malých číselnících (nikdy nevíš kdy ty číselníky nabobtnají)

 
Odpovědět 25.4.2014 7:12
Avatar
Odpovídá na turlogh
Michal Štěpánek:25.4.2014 7:23

Je pravda, že "můžeme se JOINům vyhýbat" není zrovna šťastně napsáno, ale myslím, že to bylo myšleno tak, že tu ta možnost je. Osobně bych též spojení tabulek pomocí WHERE nedoporučoval, nehledě k tomu, že když ve Visual Studiu naklikám SQL dotaz pomocí návrháře, tak mi VS vytvoří automaticky JOIN a nespojuje tabulky pomocí WHERE...

Odpovědět 25.4.2014 7:23
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na turlogh
David Čápka:25.4.2014 9:22

Že to RDBMS převede na joiny jsem psal, že to nemusí být optimálnější jsem psal taky. Kde je tedy problém? Proč nazýváš korektní konstrukci "také absolutní blbostí?". Proč také? Napsal jsi jen to, co je v článku, pokud máš konkrétní nápad na úpravu, tak sem s ním. Nezlob se na mě, ale tohle je jen tlachání.

Odpovědět  +1 25.4.2014 9:22
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
turlogh
Člen
Avatar
turlogh:25.4.2014 10:18

Článek je napsaný docela obstojně, až na tu část s tím "wherováním". Ukázat jak lze spojit 2 tabulky přes where se dá v části, kde se popisuje syntaxe příkazu select ... ale je dobré zmínit, že u velkých tabulek se tento postup nedoporučuje, protože je velmi náročný na čas a použitou paměť.
V článku věnovaném dotazům přes více tabulek pomocí JOIN bych naopak čekal, že autor/autoři zmíní, že toto je ta správná náhrada za "spojení tabulek přes where".
Pokud mi čistě náhodou ve vývoji některých RDBMS uniklo, že autoři udělali optimalizaci při které poznají, že "select * from A, B where A.ID=B.A_ID" má nahradit za "select * from A left join B on A.ID=B.A_ID", pak prosím ... ale silně o tom pochybuji a navíc je celá řada RDBMS, která tohle určitě neumí. Nahoře jste se obuli do MrPabloz za to, že poukázal na tato konstrukce je nevhodná ... a ona skutečně není vhodná.
Nemám zájem na flame, jen považuji za vhodné alespoň v diskusi vyjádřit názor člověka s mnohaletou praxí na to, že ne vše zmíněné v článku je dostatečně srozumitelné pro laika, aby věděl co si vybrat. Ten závěr totiž působí tak, že JOIN není nutný ... já tvrdím, že je. V naprosté většině případů. Když už nic jiného, prokáže tím autor dotazu svou odbornost.

 
Odpovědět  -1 25.4.2014 10:18
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na turlogh
David Čápka:25.4.2014 10:36

Díky za hodnotný komentář. Mám dojem, že když jsem článek psal, dal jsem dotaz s WHERE do optimizeru a vygenerovalo to normálně INNER JOIN. Samozřejmě je otázka jak se na to lze spolehnout.

MrPabloz psal něco úplně jiného, říkal, že to místo wherování máme nazvat "podmínka", ne že to je špatně. A potom že místo termínu "dotaz přes více tabulek" musíme použít označení "spojování". Dále že už "dávno není outer join" a další nesmysly. Proto má reakce.

Článek jsem upravil tak, aby bylo jasné, že wherování je spíše teoretická záležitost.

Odpovědět 25.4.2014 10:36
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
coells
Redaktor
Avatar
Odpovídá na turlogh
coells:25.4.2014 12:29

Pokud mluvíme o T-SQL, pak podle krátké zmínky v dokumentaci výraz FROM a,b WHERE c opravdu odpovídá FROM a JOIN b ON c. Ale preferovaná metoda je použití joinů.

Více informací jsem hledal marně. Podle mého se jedná o cross-join, jenže ... optimalizace. Zkusí se využít nejlepší index, jaký je k dispozici a exekuční plán se pak opravdu tváří jako inner join.

 
Odpovědět  +1 25.4.2014 12:29
Avatar
Neaktivní uživatel:7.9.2015 14:45

Nie som schopný niektoré veci hneď pochopiť z článku, nakoľko som totálny amatér. Ale tá diskusia je tiež užitočná. Vďaka že takto vmieňate názory..

Odpovědět 7.9.2015 14:45
Neaktivní uživatelský účet
Avatar
Ondřej Pech
Člen
Avatar
Ondřej Pech:26.4.2016 9:50

Zajímalo by mě, jak napsat SQL kód, pokud mám jednu tabulku ve které zaznamenávám docházku a s druhou tabulkou (ve které mám jména návštěvníků) je schodný sloupec OsobniID ale jména mám uložená zvlášť Jméno a v dalším sloupci Příjmení. Potřeboval bych tedy podle Osobního ID vypsat jméno i příjmení.

tabulka dochazka např.
OsobniID PrvniPrichod DruhyPrichod
123456 0 1
123457 1 1

tabulka clenove např.
OsobniID Jmeno Prijmeni ...
123456 Jimmy Bourač ...
123457 Pepa Novák ...

a chtěl bych vypsat pro DruhyPrichod:
Jimmy Bourač - 1
Pepa Novák - 1

může mi někdo poradit prosím?

 
Odpovědět 26.4.2016 9:50
Avatar
Odpovídá na Ondřej Pech
Michal Štěpánek:26.4.2016 10:17
SELECT (clenove.Jmeno + ' ' + clenove.Prijmeni) AS Zamestnanec, dochazka.DruhyPrichod FROM dochazka INNER JOIN clenove ON clenove.OsobniID = dochazka.OsobniId WHERE dochazka.DruhyPrichod = '1'
Odpovědět 26.4.2016 10:17
Nikdy neříkej nahlas, že to nejde. Vždycky se totiž najde blbec, který to neví a udělá to...
Avatar
Ondřej Pech
Člen
Avatar
Odpovídá na Michal Štěpánek
Ondřej Pech:26.4.2016 10:53

To by mohlo fungovat, díky :)

 
Odpovědět 26.4.2016 10:53
Avatar
Ondřej Krsička
Redaktor
Avatar
Ondřej Krsička:30.4.2016 20:23

Jak napíšu dotaz, který v prvním sloupci vypíše uživatele a ve druhém počet jeho článků?

 
Odpovědět 30.4.2016 20:23
Avatar
Ondřej Krsička
Redaktor
Avatar
Odpovídá na Ondřej Krsička
Ondřej Krsička:30.4.2016 20:34

jejich článků*

 
Odpovědět 30.4.2016 20:34
Avatar
Odpovídá na Ondřej Krsička
Michal Žůrek - misaz:30.4.2016 21:26
SELECT [Uzivatele].[Prezdivka], COUNT(*) AS [PocetClanku]
FROM [Clanky]
JOIN [Uzivatele] ON [Uzivatele].[Id] = [Clanky].[AutorId]
GROUP BY [Clanky].[AutorId],[Uzivatele].[Prezdivka];
 
Odpovědět  +1 30.4.2016 21:26
Avatar
Ondřej Krsička
Redaktor
Avatar
Odpovídá na Michal Žůrek - misaz
Ondřej Krsička:1.5.2016 10:54

Díky, akorát na posledním řádku nechápu to , [Uzivatele].[Prez­divka];

 
Odpovědět 1.5.2016 10:54
Avatar
Odpovídá na Ondřej Krsička
Michal Žůrek - misaz:1.5.2016 11:12

tak to zkus smazat a uvidíš. :) Ono když se nad tím hooodně hluboce zamyslíš, tak to dává smysl, prostě když používáš GROUP BY, tak musí být všechny řádky podle něčeho seskupené nesmí existovat řádek, který by obsahoval možnost díky které by nebyl seskupitelný, tudíž všechno co jde do výstupu musí být seskupeno (nějak). Snad jsem se při tom popisu v tom sám nezamotal.

 
Odpovědět 1.5.2016 11:12
Avatar
Ondřej Krsička
Redaktor
Avatar
 
Odpovědět 1.5.2016 11:14
Avatar
Mirek Senk
Člen
Avatar
Mirek Senk:31.8.2016 15:34

Ahoj, ve vzoru syntaxe na přidání osoby se špatným číslem chybí jedna hranatá závorka před AutorId

INSERT INTO [Clanky] (AutorId], ... má být INSERT INTO [Clanky] ([AutorId], ...

Jinak strašně moc děkuju za tyhle lekce!

 
Odpovědět 31.8.2016 15:34
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Mirek Senk
David Čápka:31.8.2016 15:36

Díky, opraveno :)

Odpovědět 31.8.2016 15:36
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Jakub Bómíček Bohm:5.10.2017 20:22

Zdravím. Po přečtení této lekce jsem konečně pochopil joiny a podobně. Jenom by mě zajímalo, proč nepoužíváte u vazeb 1 : N cizí klíče. Poté by se dalo vyhnout problémům s neexistujícím článkem pro toho uživatele, nebo neexistujícím uživatelem pro článek. Tím pádem by se outer join vůbec nemusel používat, jelikož by ani nešlo zadat špatné id.

 
Odpovědět 5.10.2017 20:22
Avatar
Odpovídá na Jakub Bómíček Bohm
Michal Žůrek - misaz:5.10.2017 20:26

Cizí klíče by to samozřejmě vyřešili. Články jsou přepis článků myslím z MySQL. Nepoužívají se zde z historických důvodů. OUTER JOIN by se musel používat, protože vybíráte uživatele z tabulky články. Už ta předchozí věta zní divně. Pokud nebude existovat článek k osobě, tak prostě za normálních okolností smůla. OUTER JOIN, tam dá tu osobu s hodnotami NULL všude kde nejsou.

 
Odpovědět 5.10.2017 20:26
Avatar
Jakub Bómíček Bohm:5.10.2017 20:37

Jo už jsem to pochopil. Když vkládám ty články, tak zadávám id autora ( primární klíč autora ). V tomto případě nezadávám emu - zadávám jen 1,2,2,3 -, takže bych pak použil ten right outer join a vypsalo mi to, že ema nemá žádný článek. Šlo mi jen o ten článek s id autora 99, to by nešlo vůbec vytvořit s použitím cizího klíče.

 
Odpovědět  +1 5.10.2017 20:37
Avatar
Odpovídá na Jakub Bómíček Bohm
Michal Žůrek - misaz:5.10.2017 20:45

Přesně tak. Otázkou je taky jestli v době GPDR (nebo jak se to jmenuje) to dokonce bez cizích klíčů není v něčem trochu lepší.

 
Odpovědět 5.10.2017 20:45
Avatar
Jakub Ondrák:21.6.2018 16:33

když ve Visual Studiu naklikám SQL dotaz pomocí návrháře, tak mi VS vytvoří automaticky JOIN a nespojuje tabulky pomocí WHERE...

Ahoj, prosím, kde najdu toho návrháře? :-)

 
Odpovědět 21.6.2018 16:33
Avatar
Petra D.
Člen
Avatar
Petra D. :12.9.2018 10:32

Ahoj, zkoušela jsem tento příkaz výše pro zobrazení počtu článků uživatele:

SELECT [Uzivatele].[Prez­divka], COUNT(*) AS [PocetClanku]
FROM [Clanky]
JOIN [Uzivatele] ON [Uzivatele].[Id] = [Clanky].[AutorId]
GROUP BY [Clanky].[Auto­rId],[Uzivate­le].[Prezdivka];

a nezobrazí to Emu, která nenapsala žádný článek. Pokud přidám RIGHT JOIN aby se zohlednily i uživatelé bez připojených článků, tak mi to zase napíše počet článků u Emy 1, protože se započítá i NULL. Dá se toto nějak ošetřit, abych viděla pravdivě i uživatele, kteří mají 0 článků? Díky za radu :)

Editováno 12.9.2018 10:33
Odpovědět 12.9.2018 10:32
Jaký si to uděláš, takový to máš...
Avatar
Jirka
Člen
Avatar
Odpovídá na Petra D.
Jirka:12.9.2018 11:11

Ahoj,
existuje podmínka nebo funkce if (NULL) then 0, else "sloupec". Je to v manuálu.

HTH

Odpovědět 12.9.2018 11:11
Kdo nic nedělá, nic nezkazí.
Avatar
Petra D.
Člen
Avatar
Odpovídá na Jirka
Petra D. :12.9.2018 11:13

Díky moc za nasměrování, k podmínkám v SQL jsem se ještě nedostala ;)

Odpovědět 12.9.2018 11:13
Jaký si to uděláš, takový to máš...
Avatar
Jirka
Člen
Avatar
Jirka:12.9.2018 11:24

Nemáš zač.

Ta syntaxe je nějak takto:

select SLOUPEC, if SLOUPEC2=NULL then 0 else SLOUPEC2
from tabulka
where podminka
group by SLOUPEC2;
Odpovědět 12.9.2018 11:24
Kdo nic nedělá, nic nezkazí.
Avatar
Jirka
Člen
Avatar
Odpovídá na Petra D.
Jirka:12.9.2018 14:39

Již chápu.

Tak zkus tento dotaz (zkoušeno na MariaDB):

SELECT U.Prezdivka, COUNT(C.Id) AS PocetClanku
FROM Uzivatele as U
LEFT JOIN Clanky as C ON U.Id = C.AutorId
GROUP BY U.Prezdivka;
Odpovědět 12.9.2018 14:39
Kdo nic nedělá, nic nezkazí.
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 34 zpráv z 34.