MS Access - Příkaz INNER JOIN

5. 12. 2012, Vladimír Klaus, Komentáře (6), přečteno 27538x

MS Access
SQL

Tak tímto se dají spojovat tabulky. Tedy ne fyzicky, ale třeba při použití příkazu SELECT může být výsledkem spojení tabulek. K čemu je to dobré? Tak například potřebujeme znát detailní informace o objednávce, tedy jak parametry objednávky, tak i údaje o zákazníkovi, který ji učinil.

Poznámka: V některých databázích stačí napsat pouze JOIN.

A takové informace jsou ve dvou tabulkách, které musíme spojit. Spojení musíme provést přes nějakou společnou hodnotu, což je v tomto případě ID zákazníka. V tabulce objednávek se pole jmenuje IdZakaznika a v tabulce zákazníků je to ID. Protože ale i tabulka objednávek obsahuje pole ID, musíme použít místo pouhého ID celý zápis (včetně názvu tabulky) – Zakaznici.ID. A nakonec vůbec nezaškodí (často je to dokonce nutnost), když název tabulky použijeme i u druhého sloupce - Objednavky.IdZakaznika.

SELECT * FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID

Výsledkem je krásné spojení dvou tabulek. Zároveň platí, že v tomto výsledku budou spojeny řádky pouze tehdy, pokud je v obou nalezeno stejné ID zákazníka. A naopak (zjednodušeně řečeno) – pokud existuje záznam o objednávce od neexistujícího zákazníka, nebo existuje zákazník, který si nic neobjednal, ve výsledku nebude! Porovnejte prosím s LEFT JOIN a RIGHT JOIN.

SQL obrázek

Teď si zkusíme trochu komplikovanější úkol. Zjistit, jaká je celková výše objednávek zákazníků z Prahy 8. Začneme úpravou dotazu tak, aby se nám vyfiltrovaly pouze objednávky z požadovaného města.

SELECT * FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID
  WHERE Zakaznici.Mesto = "Praha 8"

SQL obrázek

A teď už můžeme využít znalosti z agregačních funkcí a vložíme sčítací funkci.

SELECT SUM(Objednavky.Castka) FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID
WHERE Zakaznici.Mesto = "Praha 8"

SQL obrázek

Prima, ale nás to ještě zajímá v podrobnější podobě – podle jednotlivých adres (ulic). Obohatíme dotaz o seskupení dle Ulice, ale abychom ve výsledku viděli nejen součty, ale také ty ulice, musíme přidat Ulici i do SELECTu. Poslední úpravou bude zadání aliasu pro sloupec se součtem pomocí klíčového slova AS.

SELECT SUM(Objednavky.Castka) AS Soucet, Ulice FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID
WHERE Zakaznici.Mesto = "Praha 8"
  GROUP BY Zakaznici.Ulice

SQL obrázek

V dalším příkladu si ukážeme, jak zjistit objednávky od uživatele Soboty, které jsou za více než 500 Kč. Samozřejmě musíme začít tím, že propojíme Zákazníky a Objednávky přes ID zákazníka. Následně přidáme dvě podmínky na částku a jméno.

SELECT Objednavky.*, Zakaznici.Prijmeni FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID
WHERE Objednavky.Castka > 500 AND Zakaznici.Prijmeni = "Sobota"

SQL obrázek

Poznámka: Příkaz INNER JOIN lze plnohodnotně nahradit zapsáním propojovacích podmínek do příkazu WHERE a uvedením obou tabulek za příkaz FROM.

Předchozí příklad tedy můžeme zapsat i takto:

SELECT Objednavky.*, Zakaznici.Prijmeni FROM Objednavky, Zakaznici
WHERE Objednavky.IdZakaznika = Zakaznici.ID
AND Objednavky.Castka > 500
AND Zakaznici.Prijmeni ="Sobota"


Komentáře k článku (6)

20. 9. 2014 19:05:28 - Andrea Vokálová

Dobrý den,
pracuji v SQL a mým úkolem je pomocí vazby inner join spojit 2 tabulky podle určitého společného sloupce. To se mi podařilo díky Vašemu vysvětlení vazby inner join, ale ještě potřebuji záznamy seřadit podle příjmení a to nevím, jak udělat?! Poradíte mi prosím, jak na to - moc mi to pomůže. Mockrát děkuji Andy

20. 9. 2014 19:23:32 - Vladimír Klaus [ADMIN]

Dobrý večer Andreo,
to je jednoduché, na konec jen přidáte řazení.

Takže třeba takto:
SELECT * FROM Objednavky
INNER JOIN Zakaznici ON Objednavky.IdZakaznika = Zakaznici.ID
ORDER BY Datum

Pokud by Datum bylo v obou tabulkách (tady to není), tak pak:
ORDER BY Objednavky.Datum

No a pokud byste to chtěla sestupně, tak
ORDER BY Objednavky.Datum DESC

Je to popsané zde - http://www.sqlproblbce.cz/CZ/clanky-detail/38/prikaz-order-by

20. 11. 2014 15:11:25 - Jiří Romža

Dobrý den,
s dvěma tabulkami problém nemám, ale funguje také dotaz na 3 tabulky současně? Mám například tabulku zboží, objednávky a reklamace, potřeboval bych se dotázat tak, abych dostal počet objednávek a reklamací k jednotlivým položkám zboží.

Použil jsem příkaz:
SELECT zbozi.ID_zbozi, zbozi.nazev, SUM(objednavky.pocet) AS objednano, SUM(reklamace.pocet) AS reklamovano
FROM zbozi, objednavky, reklamace
WHERE zbozi.ID_zbozi=objednavky.ID_zbozi AND zbozi.ID_zbozi=reklamace=ID_zbozi
GROUP BY zbozi.ID_zbozi, zbozi.nazev

bohužel výsledek neodpovídá počtům, kde dělám chybu, lze vůbec takto spojit 3 tabulky?

Děkuji za radu Jirka

22. 11. 2014 19:52:12 - Vladimír Klaus [ADMIN]

Zdravím Jirko,

bez znalosti konkrétní databáze, resp. údajů se nedá říci, co je špatně. Jinak INNER JOIN, resp. spojení přes WHERE je prosté propojení 3 tabulek, což asi nemůže fungovat - spojí se jen řádky, které existují ve všech tabulkách. Pokud si tedy někdo objednal nějaké zboží, ale nikdo ho nereklamoval, tak ve výsledku nebude.

Určitě by pomohlo udělat dva selecty:
1) Spojeni zboží a objednávky + nasoučtovat počty
2) Spojeni zboží a reklamace + nasoučtovat počty

A pak tyto výsledky spojit přes sloupec Zbozi.ID, ovšem pomocí LEFT JOIN. Tedy, aby vlevo bylo všechno zboží/objednávky a vpravo reklamace (občas bude NULL).

19. 12. 2014 12:38:32 - Martin Papík

Dobrý den,
mám tabulky UZIVATEL a TYM. Propojení je 1:1 pomocí uzivatel.id_tym=tym.id.
V tabulce TYM je id_vedouciho, který je v tabulce UZIVATEL.
SELECTEM s INNER JOIN propojím uživatele a získám k němu tým. Můžu v jednom selectu ještě získat jméno vedoucího?

Když napíšu selekty zvlášť, není to problém:
select o.pin, o.prijmeni,o.linka
from cis_operatori as o
inner join cis_tymy as t on (o.id_tym=t.id)

select t.nazev as tym,o.prijmeni as manager
from cis_tymy as t
inner join cis_operatori as o on (t.id_vedouci=o.id)

Lze tyto dva selecty spojit dohromady, abych položky příjmení, tým, manažer měl vždy v jednom řádku?

Děkuji předem za odpověď
Martin Papík

P.S.
S SQL začínám a proto se omlouvám za třeba triviální dotaz.

19. 12. 2014 15:27:39 - Vladimír Klaus [ADMIN]

Zdravím Martine!

To se vůbec neomlouvejte, žádný dotaz není úplně triviální :-)

INNER JOIN můžete použít opakovaně, jako třeba zde. Je to trochu nepřehledné (odmyslete si ty uvozovky a +), ale snad jako příklad postačí. Takto se tedy spojí 4 tabulky:

"SELECT * FROM UserProfile "+
"INNER JOIN webpages_UsersInRoles "+
"ON UserProfile.UserId=webpages_UsersInRoles.UserId "+
"INNER JOIN webpages_Roles "+
"ON webpages_UsersInRoles.RoleId=webpages_Roles.RoleId "+
"INNER JOIN webpages_Membership "+
"ON webpages_Membership.UserId=UserProfile.UserId "+
"ORDER BY UserProfile.UserId DESC";

Komentáře mohou přidávat pouze přihlášení uživatelé.