Většinou si při práci s SQL databází nevystačíme pouze s 1 tabulkou. Některé hodnoty se nacházejí v jedné tabulce a další hodnoty v druhé = v rozdělení informací do mnoha tabulek , které jsou mezi sebou propojeny (přes klíče) spočívá podstata relačních databází.
Existují 5 základních druhů joinů: INNER JOIN, LEFT JOIN (aktuální článek), RIGHT JOIN, CROSS JOIN, FULL JOIN
Tip: Příkaz LEFT OUTER JOIN a LEFT JOIN je ekvivalentní
Syntaxe LEFT OUTER JOIN
SELECT
[Tabulka_A].[Sloupec 1]
,[Tabulka_A].[Sloupec 2]
,[Tabulka_B].[Sloupec 3]
FROM [Tabulka_A]
LEFT OUTER JOIN [Tabulka_B]
ON [Tabulka_A].[Id] = [Tabulka_B].[Id]
Představme si 2 tabulky a každá z těchto tabulek bude obsahovat pouze 1 sloupec [cislo]:
- Tabulka A obsahuje sloupec [cislo]: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
- Tabulka B obsahuje sloupec [cislo]: 1, 2, 3, 100,150
Co bude výsledkem skriptu?
SELECT
[Tabulka_A].[Cislo], [Tabulka_B].[Cislo]
FROM [Tabulka_A]
LEFT JOIN [Tabulka_B]
ON [Tabulka_A].[Cislo] = [Tabulka_B].[Cislo];
Výsledkem bude 10 řádků:
Tip: Podívejte se na příklady všech typů spojování tabulek ať pochopíte rozdíly mezi nimi. U všech používám stejný příklad – fotbalové týmy
Příklad na LEFT JOIN s fotbalovými týmy
Princip spojování tabulek si ukážeme na příkladu s fotbalovými týmy. Mějme 2 tabulky, prohlédněte si je:
- [Fotbalove_tymy] ([ID], [Tym], [Id_mesto]) – tabulka se seznamem fotbalových týmů
- [Mesta] ([ID], [Nazev_mesta]) – tabulka s městy
Zobrazíme si seznam fotbalových týmů a k nim domácí město, skript bude vypadat takto:
SELECT
[Fotbalove_tymy].[ID]
,[Fotbalove_tymy].[Tym]
,[Mesto].[Mesto]
FROM [Fotbalove_tymy]
LEFT JOIN [Mesto]
ON [Fotbalove_tymy].[Id_Mesto] = [Mesto.Id];
Vytváříme relaci mezi tabulkami. Podmínku, na základě které se nám záznamy v obou tabulkách spojí leží v ON klauzuli ([Fotbalove_tymy].[Id_Mesto] = [Mesto].[Id]).
Ve výsledku máme narozdíl od INNER JOIN všechny fotbalové týmy uvedené v tabulce [Fotbalove_tymy]. Brněnský tým je zobrazen (levá tabulka), ale protože neexistuje záznam v tabulce s městy s [město_id] = 0 je hodnota [mesto] = NULL – prozkoumejte rozdíl u stejného příkladu v případě inner joinu.
Dobrý den,
Vaše stránky jsou skvělí pomocník, nejsem programátor a asi nikdy nebudu, nicméně díky Vašim stránkám jsem si z našeho účetního mohl vytahat data a poskládat si je reportech které potřebuji ke své práci, moc děkuji.
A ted k dotazu:
Spojuji dvě tabulky. Levá tabulka je databáze produktů (
ID 1 = cihla, optimální zásoba 10ks
ID 2 = cement, optimální zásoba 8ks)
a k těmto produktům potřebuji doplnit aktuální zásobu na skladě a průměrnou cenu zádoby tj mám pravou tabulku která obsahuje tyto řádky (
ID 1 = 10ks 100,-Kč
ID 1 = 5ks 80Kč
ID 1 = 8ks 90,-Kč
ID 1 = 7ks 100,-Kč)
Spojit je umím, problém je že tu pravou tabulku potřebuji asi předtím sečíst aby každý řádek v pravé tabulce byl jen jednou a to už neumím – takto se mi tam opakují duplicitně stejné hodnoty z levé tabulky. Pokud by to bylo 1:1 tak se mi to daří, ale takto už jsem nemydlenej
Děkuji za radu
Ahoj Pavle,
za mě palec nahoru, že jsi udělal první krok k tomu naučit se SQL a zjednodušit si do budoucna práci. K tvému problému:
(i) Když se nad tím zamyšlíš tak ano, můžeš problém řešit tak, že v pravé tabulce nejprve uděláš SUMU přes ProductID a pak teprve ty 2 tabulky zjoinuješ, to by vypadalo nějak takhle:
SELECT
a.ProductID,
a.OptimalniZAsoba
b.AktualniZasoba
a.OptimalniZAsoba – AktualniZasoba AS Deficit
FROM TabulkaProdukt a
LEFT JOIN (SELECT ProductID, SUM(AktualniZasoba) AS AktualniZasoba FROM TabulkaSklad GROUP BY ProductID) b
ON a.ProductID = b.PRoductID
Výsledek budou productID s aktuální hodnotou zásob a deficitem.
(ii) Můžeš to ale udělat v tomto případě tak, že nejprve tabulky zjoinujes a pak provedeš agregaci:
SELECT
a.ProductID,
a.OptimalniZAsoba
SUM(b.AktualniZasoba) AS AktualniZasoba
a.OptimalniZAsoba – SUM(b.AktualniZasoba) AS Deficit
FROM TabulkaProdukt a
LEFT JOIN TabulkaSklad b
ON a.ProductID = b.PRoductID
GROUP BY a.ProductID,
a.OptimalniZAsoba
Odkaz na článek o agregačních funkcích zde na webu: https://janzednicek.cz/sql-agregacni-funkce/
Doufám že tam někde nemám chybu, psal jsem to narychlo u kafe, ale snad tě to nakoplo ke správnému řešení