Připojte se (SQL) - Join (SQL) - Wikipedia
An SQL připojit se klauzule - odpovídá a spojovací operace v relační algebře - kombinuje sloupce od jednoho nebo více tabulky v relačním databáze. Vytvoří sadu, kterou lze uložit jako tabulku nebo použít tak, jak je. A PŘIPOJIT SE
je prostředek pro kombinování sloupce z jedné (self-join) nebo více tabulek pomocí hodnot společných pro každou z nich. ANSI -standard SQL specifikuje pět typů PŘIPOJIT SE
: VNITŘNÍ
, VLEVO VNĚJŠÍ
, VPRAVO VNĚJŠÍ
, PLNÝ VNĚJŠÍ
a PŘEJÍT
. Jako speciální případ může být stůl (základní stůl, Pohled, nebo spojený stůl) může PŘIPOJIT SE
pro sebe v a samostatně se připojit.
Programátor deklaruje a PŘIPOJIT SE
příkaz k identifikaci řádků pro připojení. Pokud je vyhodnocený predikát pravdivý, kombinovaný řádek se poté vytvoří v očekávaném formátu, sadě řádků nebo dočasné tabulce.
Ukázkové tabulky
Relační databáze jsou obvykle normalizováno eliminovat duplikaci informací, například když mají typy entit vztahy jedna k mnoha. Například oddělení může být spojeno s počtem zaměstnanců. Spojením samostatných tabulek pro oddělení a zaměstnance se efektivně vytvoří další tabulka, která kombinuje informace z obou tabulek.
Všechna následující vysvětlení typů spojení v tomto článku využívají následující dvě tabulky. Řádky v těchto tabulkách slouží k ilustraci účinku různých typů spojení a predikátů spojení. V následujících tabulkách ID oddělení
sloupec z oddělení
stůl (který lze označit jako Department.DepartmentID
) je primární klíč, zatímco Employee.DepartmentID
je cizí klíč.
Příjmení | ID oddělení |
---|---|
Rafferty | 31 |
Jones | 33 |
Heisenberg | 33 |
Robinson | 34 |
Kovář | 34 |
Williams | NULA |
ID oddělení | DepartmentName |
---|---|
31 | Odbyt |
33 | Inženýrství |
34 | Administrativní |
35 | Marketing |
Poznámka: Ve výše uvedené tabulce Zaměstnanec nebyl zaměstnanec „Williams“ dosud přiřazen k žádnému oddělení. Pamatujte také, že do oddělení „Marketing“ nejsou přiřazeni žádní zaměstnanci.
Toto je příkaz SQL k vytvoření výše uvedených tabulek.
1VYTVOŘIT STŮL oddělení( 2 ID oddělení INT HLAVNÍ KLÍČ NE NULA, 3 DepartmentName VARCHAR(20) 4); 5 6VYTVOŘIT STŮL zaměstnanec ( 7 Příjmení VARCHAR(20), 8 ID oddělení INT REFERENCE oddělení(ID oddělení) 9);1011VLOŽIT DO oddělení12HODNOTY (31, 'Odbyt'),13 (33, 'Inženýrství'),14 (34, ‚Administrativní '),15 (35, 'Marketing');1617VLOŽIT DO zaměstnanec18HODNOTY ('Rafferty', 31),19 (‚Jones ', 33),20 ('Heisenberg', 33),21 ('Robinson', 34),22 ('Kovář', 34),23 ('Williams', NULA);
Křížové spojení
CROSS JOIN vrátí kartézský součin řádků z tabulek ve spojení. Jinými slovy, vytvoří řádky, které kombinují každý řádek z první tabulky s každým řádkem z druhé tabulky.[1]
Příklad explicitního křížového spojení:
VYBRAT *Z zaměstnanec PŘEJÍT PŘIPOJIT SE oddělení;
Příklad implicitního křížového spojení:
VYBRAT *Z zaměstnanec, oddělení;
Křížový spoj lze nahradit vnitřním spojem se vždy platnou podmínkou:
VYBRAT *Z zaměstnanec VNITŘNÍ PŘIPOJIT SE oddělení NA 1=1;
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName | Department.DepartmentID |
---|---|---|---|
Rafferty | 31 | Odbyt | 31 |
Jones | 33 | Odbyt | 31 |
Heisenberg | 33 | Odbyt | 31 |
Kovář | 34 | Odbyt | 31 |
Robinson | 34 | Odbyt | 31 |
Williams | NULA | Odbyt | 31 |
Rafferty | 31 | Inženýrství | 33 |
Jones | 33 | Inženýrství | 33 |
Heisenberg | 33 | Inženýrství | 33 |
Kovář | 34 | Inženýrství | 33 |
Robinson | 34 | Inženýrství | 33 |
Williams | NULA | Inženýrství | 33 |
Rafferty | 31 | Administrativní | 34 |
Jones | 33 | Administrativní | 34 |
Heisenberg | 33 | Administrativní | 34 |
Kovář | 34 | Administrativní | 34 |
Robinson | 34 | Administrativní | 34 |
Williams | NULA | Administrativní | 34 |
Rafferty | 31 | Marketing | 35 |
Jones | 33 | Marketing | 35 |
Heisenberg | 33 | Marketing | 35 |
Kovář | 34 | Marketing | 35 |
Robinson | 34 | Marketing | 35 |
Williams | NULA | Marketing | 35 |
Křížové spojení samo o sobě nepoužije žádný predikát k filtrování řádků ze spojené tabulky. Výsledky křížového spojení lze filtrovat pomocí a KDE
klauzule, která pak může vytvořit ekvivalent vnitřního spojení.
V SQL: 2011 standardní, křížové spoje jsou součástí volitelného balíčku F401, "Rozšířené spojené tabulky".
Normální použití slouží ke kontrole výkonu serveru.
Vnitřní spojení

An vnitřní spojení vyžaduje, aby každý řádek ve dvou spojených tabulkách měl shodné hodnoty sloupců a je běžně používanou operací spojení v aplikace ale nemělo by se to považovat za nejlepší volbu ve všech situacích. Vnitřní spojení vytvoří novou tabulku výsledků kombinací hodnot sloupců dvou tabulek (A a B) na základě predikátu spojení. Dotaz porovnává každý řádek A s každým řádkem B, aby našel všechny páry řádků, které splňují predikát spojení. Když je spojovací predikát uspokojen porovnánímNULA hodnoty, hodnoty sloupců pro každou shodnou dvojici řádků A a B se spojí do řádku výsledků.
Výsledek spojení lze definovat jako výsledek prvního převzetí kartézský součin (nebo Křížové spojení ) všech řádků v tabulkách (kombinace každého řádku v tabulce A s každým řádkem v tabulce B) a následné vrácení všech řádků, které splňují predikát spojení. Skutečné implementace SQL obvykle používají jiné přístupy, například hash se připojí nebo spojení třídění a slučování, protože výpočet kartézského součinu je pomalejší a jeho uložení by často vyžadovalo neúnosně velké množství paměti.
SQL specifikuje dva různé syntaktické způsoby, jak vyjádřit spojení: „explicitní zápis spojení“ a „implicitní zápis spojení“. „Implicitní spojovací notace“ již není považována za osvědčený postup, ačkoli ji databázové systémy stále podporují.
"Explicitní zápis spojení" používá PŘIPOJIT SE
klíčové slovo, volitelně před ním VNITŘNÍ
klíčové slovo, chcete-li určit tabulku, ke které se chcete připojit, a NA
klíčové slovo k určení predikátů spojení, jako v následujícím příkladu:
VYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, oddělení.DepartmentName Z zaměstnanec VNITŘNÍ PŘIPOJIT SE oddělení NAzaměstnanec.ID oddělení = oddělení.ID oddělení;
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
Robinson | 34 | Administrativní |
Jones | 33 | Inženýrství |
Kovář | 34 | Administrativní |
Heisenberg | 33 | Inženýrství |
Rafferty | 31 | Odbyt |
"Implicitní zápis spojení" jednoduše uvádí seznam tabulek pro připojení v souboru Z
klauzule VYBRAT
a oddělte je čárkami. Určuje tedy a křížové spojení a KDE
klauzule může použít další predikáty filtru (které fungují srovnatelně s predikáty spojení ve výslovné notaci).
Následující příklad je ekvivalentní předchozímu, ale tentokrát pomocí implicitní notace spojení:
VYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, oddělení.DepartmentName Z zaměstnanec, odděleníKDE zaměstnanec.ID oddělení = oddělení.ID oddělení;
Dotazy uvedené v příkladech výše se připojí k tabulkám zaměstnanců a oddělení pomocí sloupce DepartmentID obou tabulek. Pokud se DepartmentID těchto tabulek shoduje (tj. Predikát spojení je splněn), bude dotaz kombinovat Příjmení, ID oddělení a DepartmentName sloupce ze dvou tabulek do řádku výsledků. Pokud se DepartmentID neshoduje, není vygenerován žádný řádek výsledku.
Výsledek provedení výše uvedeného dotazu bude:
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
Robinson | 34 | Administrativní |
Jones | 33 | Inženýrství |
Kovář | 34 | Administrativní |
Heisenberg | 33 | Inženýrství |
Rafferty | 31 | Odbyt |
Zaměstnanec „Williams“ a oddělení „Marketing“ se ve výsledcích provedení dotazu neobjeví. Ani jeden z nich nemá žádné odpovídající řádky v jiné příslušné tabulce: „Williams“ nemá žádné přidružené oddělení a žádný zaměstnanec nemá ID oddělení 35 („Marketing“). V závislosti na požadovaných výsledcích může být toto chování jemnou chybou, které lze zabránit nahrazením vnitřního spojení znakem vnější spojení.
Vnitřní hodnoty spojení a NULL
Programátoři by měli dávat zvláštní pozor při spojování tabulek na sloupcích, které mohou obsahovat NULA hodnoty, protože NULL nikdy nebude odpovídat žádné jiné hodnotě (ani samotné NULL), pokud podmínka spojení výslovně nepoužívá predikát kombinace, který nejprve zkontroluje, zda jsou sloupce spojení NENULOVÝ
před uplatněním zbývajících predikátových podmínek. Vnitřní spojení lze bezpečně použít pouze v databázi, která vynucuje referenční integrita nebo kde je zaručeno, že sloupce spojení nebudou NULL. Mnoho zpracování transakcí relační databáze se spoléhají Atomicita, konzistence, izolace, trvanlivost (ACID) standardy pro aktualizaci dat, aby byla zajištěna integrita dat, takže vnitřní spojení je vhodnou volbou. Databáze transakcí však obvykle také mají žádoucí sloupce spojení, u nichž je povoleno mít hodnotu NULL. Mnoho zpráv relační databáze a datové sklady použijte velkou hlasitost Extrahovat, transformovat, načíst (ETL) dávkové aktualizace, které ztěžují nebo znemožňují vynucení referenční integrity, což má za následek potenciálně NULL připojení sloupců, které autor dotazu SQL nemůže upravit, a které způsobí, že vnitřní spojení vynechají data bez indikace chyby. Volba použití vnitřního spojení závisí na návrhu databáze a charakteristikách dat. Levé vnější spojení lze obvykle nahradit vnitřním spojením, když sloupce spojení v jedné tabulce mohou obsahovat hodnoty NULL.
Jakýkoli datový sloupec, který může být NULL (prázdný), by nikdy neměl být použit jako odkaz ve vnitřním spojení, pokud není zamýšleným výsledkem vyloučení řádků s hodnotou NULL. Pokud mají být sloupce NULL join záměrně odstraněny z sada výsledků, vnitřní spojení může být rychlejší než vnější spojení, protože spojení a filtrování tabulky se provádí v jediném kroku. Naopak vnitřní spojení může mít za následek katastroficky pomalý výkon nebo dokonce selhání serveru, když se použije v dotazu na velký objem v kombinaci s databázovými funkcemi v klauzuli SQL Where.[2][3][4] Funkce v klauzuli SQL Where může vést k tomu, že databáze ignoruje relativně kompaktní indexy tabulek. Databáze může číst a vnitřní spojení s vybranými sloupci z obou tabulek před snížením počtu řádků pomocí filtru, který závisí na vypočítané hodnotě, což vede k relativně enormnímu množství neefektivního zpracování.
Když se sada výsledků vytvoří spojením několika tabulek, včetně hlavních tabulek použitých k vyhledání úplných textových popisů číselných identifikačních kódů (a Vyhledávací tabulka ), hodnota NULL v kterémkoli z cizích klíčů může mít za následek vyloučení celého řádku ze sady výsledků bez indikace chyby. Složitý dotaz SQL, který zahrnuje jedno nebo více vnitřních spojení a několik vnějších spojení, má stejné riziko pro hodnoty NULL ve sloupcích vnitřního spojení.
Závazek k kódu SQL obsahujícímu vnitřní spojení předpokládá, že sloupce NULL join nebudou zavedeny budoucími změnami, včetně aktualizací dodavatelů, změn designu a hromadného zpracování mimo pravidla pro ověření dat aplikace, jako jsou převody dat, migrace, hromadné importy a slučování.
Lze dále klasifikovat vnitřní spojení jako rovnocenná spojení, jako přirozená spojení nebo jako křížová spojení.
Equi-join
An equi-join je specifický typ spojení založeného na komparátoru, který používá pouze rovnost srovnání v predikátu spojení. Použití dalších operátorů porovnání (například <
) diskvalifikuje spojení jako rovnocenné spojení. Dotaz zobrazený výše již poskytl příklad equi-join:
VYBRAT *Z zaměstnanec PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID oddělení;
Můžeme napsat equi-join jak je uvedeno níže,
VYBRAT *Z zaměstnanec, odděleníKDE zaměstnanec.ID oddělení = oddělení.ID oddělení;
Pokud mají sloupce v equi-join stejný název, SQL-92 poskytuje volitelnou zkratkovou notaci pro vyjádření rovných spojení prostřednictvím POUŽITÍM
postavit:[5]
VYBRAT *Z zaměstnanec VNITŘNÍ PŘIPOJIT SE oddělení POUŽITÍM (ID oddělení);
The POUŽITÍM
konstrukt je více než pouhý syntaktický cukr protože se však výsledková sada liší od výsledkové sady verze s explicitním predikátem. Konkrétně všechny sloupce uvedené v souboru POUŽITÍM
seznam se zobrazí pouze jednou s nekvalifikovaným názvem, nikoli jednou pro každou tabulku ve spojení. Ve výše uvedeném případě bude jediný ID oddělení
sloupec a č zaměstnanec. ID oddělení
nebo oddělení. ID oddělení
.
The POUŽITÍM
klauzule není podporována MS SQL Serverem a Sybase.
Přirozené spojení
Přirozené spojení je speciální případ equi-join. Přirozené spojení (⋈) je a binární operátor to je psáno jako (R ⋈ S) kde R a S jsou vztahy.[6] Výsledkem přirozeného spojení je sada všech kombinací n-tice v R a S které jsou stejné na jejich společných názvech atributů. Pro příklad zvažte tabulky Zaměstnanec a Odd a jejich přirozené spojení:
|
|
|
To lze také použít k definování složení vztahů. Například složení Zaměstnanec a Odd je jejich spojení, jak je uvedeno výše, promítané na všechny kromě společného atributu DeptName. v teorie kategorií, spojení je přesně to vláknitý výrobek.
Přirozené spojení je pravděpodobně jedním z nejdůležitějších operátorů, protože je relačním protějškem logického AND. Všimněte si, že pokud se stejná proměnná objeví v každém ze dvou predikátů, které jsou spojeny pomocí AND, pak tato proměnná znamená stejnou věc a oba vzhledy musí být vždy nahrazeny stejnou hodnotou. Přirozené spojení zejména umožňuje kombinaci vztahů, které jsou spojeny a cizí klíč. Například ve výše uvedeném příkladu cizí klíč pravděpodobně drží od Zaměstnanec.DeptName na Odd.DeptName a pak přirozené spojení Zaměstnanec a Odd kombinuje všechny zaměstnance s jejich odděleními. Funguje to, protože cizí klíč drží mezi atributy se stejným názvem. Pokud tomu tak není, například v cizím klíči od Odd.manažer na Zaměstnanec.název pak je nutné tyto sloupce před přirozeným spojením přejmenovat. Takové spojení se někdy označuje také jako equi-join.
Formálněji jsou sémantika přirozeného spojení definována takto:
- ,
kde Zábava je predikát to platí pro a vztah r kdyby a jen kdyby r je funkce. To se obvykle vyžaduje R a S musí mít alespoň jeden společný atribut, ale pokud je toto omezení vynecháno, a R a S nemají žádné společné atributy, pak se přirozené spojení stane přesně kartézským součinem.
Přirozené spojení lze simulovat pomocí Coddových primitiv následovně. Nechat C1, …, Cm být společné názvy atributů R a S, r1, …, rn být názvy atributů jedinečné pro R a nechte s1, …, sk být atributy jedinečné pro S. Dále předpokládejme, že názvy atributů X1, …, Xm nejsou ani uvnitř R ani dovnitř S. V prvním kroku jsou běžné názvy atributů v S nyní lze přejmenovat:
Pak vezmeme kartézský součin a vybereme n-tice, které se mají spojit:
A přirozené spojení je typ equi-join, kde připojit se predikát vzniká implicitně porovnáním všech sloupců v obou tabulkách, které mají stejné názvy sloupců v spojených tabulkách. Výsledná připojená tabulka obsahuje pouze jeden sloupec pro každou dvojici stejně pojmenovaných sloupců. V případě, že nebudou nalezeny žádné sloupce se stejnými názvy, bude výsledkem a křížové spojení.
Většina odborníků souhlasí s tím, že PŘÍRODNÍ PŘIPOJENÍ jsou nebezpečná, a proto důrazně nedoporučují jejich používání.[7] Nebezpečí pochází z neúmyslného přidání nového sloupce, který je pojmenován stejně jako jiný sloupec v druhé tabulce. Existující přirozené spojení by pak mohlo „přirozeně“ použít nový sloupec pro srovnání a porovnávat / porovnávat pomocí jiných kritérií (z jiných sloupců) než dříve. Existující dotaz by tedy mohl přinést různé výsledky, přestože data v tabulkách nebyla změněna, ale pouze rozšířena. Použití názvů sloupců k automatickému určování odkazů na tabulky není volbou ve velkých databázích se stovkami nebo tisíci tabulek, kde by to na konvence pojmenování znamenalo nerealistické omezení. Skutečné databáze jsou běžně navrženy s cizí klíč data, která nejsou trvale vyplněna (jsou povoleny hodnoty NULL), kvůli obchodním pravidlům a kontextu. Je běžnou praxí upravit názvy sloupců podobných dat v různých tabulkách a tento nedostatek rigidní konzistence degraduje přirozené spojení s teoretickým konceptem pro diskusi.
Výše uvedený ukázkový dotaz pro vnitřní spojení lze vyjádřit jako přirozené spojení následujícím způsobem:
VYBRAT *Z zaměstnanec PŘÍRODNÍ PŘIPOJIT SE oddělení;
Stejně jako u explicitní POUŽITÍM
klauzule, v připojené tabulce se vyskytuje pouze jeden sloupec DepartmentID, bez kvalifikátoru:
ID oddělení | Zaměstnanec.Poslední jméno | Department.DepartmentName |
---|---|---|
34 | Kovář | Administrativní |
33 | Jones | Inženýrství |
34 | Robinson | Administrativní |
33 | Heisenberg | Inženýrství |
31 | Rafferty | Odbyt |
PostgreSQL, MySQL a Oracle podporují přirozená spojení; Microsoft T-SQL a IBM DB2 nikoli. Sloupce použité ve spojení jsou implicitní, takže kód spojení neukazuje, které sloupce se očekávají, a změna názvů sloupců může změnit výsledky. V SQL: 2011 standardní, přirozená spojení jsou součástí volitelného balíčku F401, "Rozšířená spojená tabulka".
V mnoha databázových prostředích jsou názvy sloupců řízeny externím dodavatelem, nikoli vývojářem dotazů. Přirozené spojení předpokládá stabilitu a konzistenci v názvech sloupců, které se mohou měnit během upgradování verze nařízené dodavatelem.
Vnější spojení
Připojená tabulka zachová každý řádek - i když neexistuje žádný jiný odpovídající řádek. Vnější spojení se dále dělí na levé vnější spojení, pravé vnější spojení a úplné vnější spojení, podle toho, které řádky tabulky jsou zachovány: vlevo, vpravo nebo obojí (v tomto případě vlevo, odjet a že jo odkazují na dvě strany PŘIPOJIT SE
klíčové slovo). Jako vnitřní spojení, lze dále podkategorizovat všechny typy vnějších spojení jako equi-joins, přirozené spojení, NA <predicate>
(θ-připojit se ), atd.[8]
Ve standardním SQL neexistuje žádná implicitní notace spojení pro vnější spojení.

Levý vnější spoj
Výsledek a levé vnější spojení (nebo jednoduše levé připojení) pro tabulky A a B vždy obsahuje všechny řádky „levé“ tabulky (A), i když podmínka spojení nenajde žádný odpovídající řádek v „pravé“ tabulce (B). To znamená, že pokud NA
klauzule odpovídá 0 (nula) řádků v B (pro daný řádek v A), spojení stále vrátí řádek ve výsledku (pro tento řádek) - ale s NULL v každém sloupci z B. A levé vnější spojení vrátí všechny hodnoty z vnitřního spojení plus všechny hodnoty v levé tabulce, které se neshodují s pravou tabulkou, včetně řádků s NULL (prázdnými) hodnotami ve sloupci odkazu.
To nám například umožňuje najít oddělení zaměstnanců, ale stále se zobrazují zaměstnanci, kteří nebyli přiřazeni k oddělení (na rozdíl od výše uvedeného příkladu vnitřního spojení, kde byli z výsledku vyloučeni nepřiřazení zaměstnanci).
Příklad levého vnějšího spojení ( VNĚJŠÍ
klíčové slovo je volitelné), s dalším řádkem výsledku (ve srovnání s vnitřním spojením) kurzívou:
VYBRAT *Z zaměstnanec VLEVO, ODJET VNĚJŠÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID oddělení;
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName | Department.DepartmentID |
---|---|---|---|
Jones | 33 | Inženýrství | 33 |
Rafferty | 31 | Odbyt | 31 |
Robinson | 34 | Administrativní | 34 |
Kovář | 34 | Administrativní | 34 |
Williams | NULA | NULA | NULA |
Heisenberg | 33 | Inženýrství | 33 |
Alternativní syntaxe
Oracle podporuje zastaralé[9] syntax:
VYBRAT *Z zaměstnanec, odděleníKDE zaměstnanec.ID oddělení = oddělení.ID oddělení(+)
Sybase podporuje syntaxi (Microsoft SQL Server zastaralá tato syntaxe od verze 2000):
VYBRAT*Zzaměstnanec,odděleníKDEzaměstnanec.ID oddělení*=oddělení.ID oddělení
IBM Informix podporuje syntaxi:
VYBRAT *Z zaměstnanec, VNĚJŠÍ odděleníKDE zaměstnanec.ID oddělení = oddělení.ID oddělení

Pravý vnější spoj
A pravé vnější spojení (nebo správně se připojit) velmi připomíná levé vnější spojení, s výjimkou obrácení tabulek. Každý řádek z „pravé“ tabulky (B) se v připojené tabulce objeví alespoň jednou. Pokud neexistuje žádný odpovídající řádek z „levé“ tabulky (A), ve sloupcích z A se zobrazí NULL pro ty řádky, které se v B. neshodují.
Pravé vnější spojení vrátí všechny hodnoty z pravé tabulky a odpovídající hodnoty z levé tabulky (NULL v případě, že neexistuje žádný odpovídající predikát spojení). To nám například umožňuje najít každého zaměstnance a jeho oddělení, ale přesto zobrazit oddělení, která nemají žádné zaměstnance.
Níže je uveden příklad pravého vnějšího spojení ( VNĚJŠÍ
klíčové slovo je volitelné), s dalším řádkem výsledku kurzívou:
VYBRAT *Z zaměstnanec ŽE JO VNĚJŠÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID oddělení;
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName | Department.DepartmentID |
---|---|---|---|
Kovář | 34 | Administrativní | 34 |
Jones | 33 | Inženýrství | 33 |
Robinson | 34 | Administrativní | 34 |
Heisenberg | 33 | Inženýrství | 33 |
Rafferty | 31 | Odbyt | 31 |
NULA | NULA | Marketing | 35 |
Pravé a levé vnější spojení jsou funkčně ekvivalentní. Ani jeden neposkytuje žádné funkce, které druhý neposkytuje, takže pravé a levé vnější spojení se mohou navzájem nahradit, pokud je přepnuto pořadí tabulky.

Úplné vnější spojení
Koncepčně, a úplné vnější spojení kombinuje účinek aplikace levého i pravého vnějšího spojení. Tam, kde se řádky v tabulkách FULL OUTER JOINED neshodují, bude mít sada výsledků NULL hodnoty pro každý sloupec tabulky, kterému chybí odpovídající řádek. U těch řádků, které se shodují, bude v sadě výsledků vytvořen jeden řádek (obsahující sloupce vyplněné z obou tabulek).
Například nám to umožňuje vidět každého zaměstnance, který je v oddělení, a každé oddělení, které má zaměstnance, ale také vidět každého zaměstnance, který není součástí oddělení, a každé oddělení, které nemá zaměstnance.
Příklad úplného vnějšího spojení ( VNĚJŠÍ
klíčové slovo je volitelné):
VYBRAT *Z zaměstnanec PLNÝ VNĚJŠÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID oddělení;
Zaměstnanec.Poslední jméno | Employee.DepartmentID | Department.DepartmentName | Department.DepartmentID |
---|---|---|---|
Kovář | 34 | Administrativní | 34 |
Jones | 33 | Inženýrství | 33 |
Robinson | 34 | Administrativní | 34 |
Williams | NULA | NULA | NULA |
Heisenberg | 33 | Inženýrství | 33 |
Rafferty | 31 | Odbyt | 31 |
NULA | NULA | Marketing | 35 |
Některé databázové systémy nepodporují přímo celou funkci vnějšího spojení, ale mohou jej emulovat pomocí vnitřního spojení a UNION ALL vybírá „řádky jedné tabulky“ z levé a pravé tabulky. Stejný příklad může vypadat následovně:
VYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, oddělení.DepartmentName, oddělení.ID odděleníZ zaměstnanecVNITŘNÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID odděleníUNIE VŠECHNOVYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, obsazení(NULA tak jako varchar(20)), obsazení(NULA tak jako celé číslo)Z zaměstnanecKDE NE EXISTUJE ( VYBRAT * Z oddělení KDE zaměstnanec.ID oddělení = oddělení.ID oddělení)UNIE VŠECHNOVYBRAT obsazení(NULA tak jako varchar(20)), obsazení(NULA tak jako celé číslo), oddělení.DepartmentName, oddělení.ID odděleníZ odděleníKDE NE EXISTUJE ( VYBRAT * Z zaměstnanec KDE zaměstnanec.ID oddělení = oddělení.ID oddělení)
Připojte se
Self-join se připojuje k sobě.[10]
Příklad
Pokud by existovaly dvě samostatné tabulky pro zaměstnance a dotaz, který by vyžadoval, aby zaměstnanci v první tabulce měli stejnou zemi jako zaměstnanci ve druhé tabulce, mohla by se k vyhledání tabulky odpovědí použít běžná operace spojení. Všechny informace o zaměstnancích jsou však obsaženy v jedné velké tabulce.[11]
Zvažte upravený Zaměstnanec
následující tabulka:
ID zaměstnance | Příjmení | Země | ID oddělení |
---|---|---|---|
123 | Rafferty | Austrálie | 31 |
124 | Jones | Austrálie | 33 |
145 | Heisenberg | Austrálie | 33 |
201 | Robinson | Spojené státy | 34 |
305 | Kovář | Německo | 34 |
306 | Williams | Německo | NULA |
Příklad dotazu na řešení může být následující:
VYBRAT F.ID zaměstnance, F.Příjmení, S.ID zaměstnance, S.Příjmení, F.ZeměZ Zaměstnanec F VNITŘNÍ PŘIPOJIT SE Zaměstnanec S NA F.Země = S.ZeměKDE F.ID zaměstnance < S.ID zaměstnanceOBJEDNAT PODLE F.ID zaměstnance, S.ID zaměstnance;
Což má za následek generování následující tabulky.
ID zaměstnance | Příjmení | ID zaměstnance | Příjmení | Země |
---|---|---|---|---|
123 | Rafferty | 124 | Jones | Austrálie |
123 | Rafferty | 145 | Heisenberg | Austrálie |
124 | Jones | 145 | Heisenberg | Austrálie |
305 | Kovář | 306 | Williams | Německo |
V tomto příkladu:
F
aS
jsou aliasy pro první a druhou kopii tabulky zaměstnanců.- Kondice
F.Country = S.Country
vylučuje párování mezi zaměstnanci v různých zemích. Ukázková otázka chtěla pouze dvojice zaměstnanců ve stejné zemi. - Kondice
F.ID zaměstnance
vylučuje párování, kde ID zaměstnance
prvního zaměstnance je větší nebo rovnoID zaměstnance
druhého zaměstnance. Jinými slovy, účinkem této podmínky je vyloučení duplicitních párování a párování. Bez ní by byla vygenerována následující méně užitečná tabulka (tabulka níže zobrazuje pouze část výsledku „Německo“):
ID zaměstnance | Příjmení | ID zaměstnance | Příjmení | Země |
---|---|---|---|---|
305 | Kovář | 305 | Kovář | Německo |
305 | Kovář | 306 | Williams | Německo |
306 | Williams | 305 | Kovář | Německo |
306 | Williams | 306 | Williams | Německo |
K uspokojení původní otázky je potřeba pouze jeden ze dvou středních párů a nejvyšší a nejspodnější nejsou v tomto příkladu vůbec zajímavé.
Alternativy
Efekt vnějšího spojení lze získat také pomocí UNION ALL mezi VNITŘNÍM PŘIPOJENÍM a VÝBĚREM řádků v „hlavní“ tabulce, které nesplňují podmínku spojení. Například,
VYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, oddělení.DepartmentNameZ zaměstnanecVLEVO, ODJET VNĚJŠÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID oddělení;
lze také napsat jako
VYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, oddělení.DepartmentNameZ zaměstnanecVNITŘNÍ PŘIPOJIT SE oddělení NA zaměstnanec.ID oddělení = oddělení.ID odděleníUNIE VŠECHNOVYBRAT zaměstnanec.Příjmení, zaměstnanec.ID oddělení, obsazení(NULA tak jako varchar(20))Z zaměstnanecKDE NE EXISTUJE ( VYBRAT * Z oddělení KDE zaměstnanec.ID oddělení = oddělení.ID oddělení)
Implementace
Hodně práce v databázových systémech se zaměřilo na efektivní implementaci spojení, protože relační systémy obvykle vyžadují spojení, přesto čelí obtížím při optimalizaci jejich efektivního provádění. Problém nastává, protože vnitřní spojení fungují oběma způsoby komutativně a asociativně. V praxi to znamená, že uživatel pouze dodá seznam tabulek pro připojení a podmínky připojení, které má použít, a databázový systém má za úkol určit nejúčinnější způsob provedení operace. A optimalizátor dotazů určuje, jak provést dotaz obsahující spojení. Optimalizátor dotazů má dvě základní svobody:
- Připojit se k objednávce: Protože spojuje funkce komutativně a asociativně, pořadí, ve kterém se systém připojuje k tabulkám, nemění konečnou sadu výsledků dotazu. Objednávka spojení mohl mít enormní dopad na cenu operace spojení, takže výběr nejlepší objednávky spojení se stává velmi důležitým.
- Připojte se k metodě: Vzhledem k tomu, dvě tabulky a podmínka spojení, více algoritmy může vytvořit sadu výsledků spojení. Který algoritmus běží nejefektivněji, závisí na velikostech vstupních tabulek, počtu řádků z každé tabulky, které odpovídají podmínce spojení, a na operacích požadovaných zbytkem dotazu.
Mnoho spojovacích algoritmů zachází se svými vstupy odlišně. Jeden může odkazovat na vstupy spojení jako "vnější" a "vnitřní" operandy spojení, nebo "vlevo" a "vpravo". Například v případě vnořených smyček prohledá databázový systém celou vnitřní relaci pro každý řádek vnější relace.
Lze klasifikovat plány dotazů zahrnující spojení takto:[12]
- hluboko doleva
- pomocí základní tabulky (spíše než dalšího spojení) jako vnitřního operandu každého spojení v plánu
- do hloubky
- pomocí základní tabulky jako vnějšího operandu každého spojení v plánu
- huňatý
- ani nalevo, ani napravo; oba vstupy do spojení mohou samy o sobě být výsledkem spojení
Tyto názvy jsou odvozeny od vzhledu plán dotazů pokud je nakreslen jako strom, s vnějším spojovacím vztahem vlevo a vnitřním vztahem vpravo (jak stanoví konvence).
Připojte se k algoritmům
Existují tři základní algoritmy pro provedení operace spojení: spojení vnořené smyčky, třídit-sloučit spojení a hash připojit.
Připojte se k indexům
Spojovací indexy jsou databázové indexy které usnadňují zpracování dotazů na spojení ve Windows datové sklady: jsou aktuálně (2012) k dispozici v implementacích od Věštec[13] a Teradata.[14]
V implementaci Teradata jsou zadané sloupce, agregační funkce na sloupcích nebo komponenty sloupců data z jedné nebo více tabulek zadány pomocí syntaxe podobné definici a zobrazení databáze: v jednom indexu spojení lze zadat až 64 sloupců / výrazů sloupců. Volitelně sloupec, který definuje primární klíč mohou být také specifikována složená data: na paralelním hardwaru se hodnoty sloupců používají k rozdělení obsahu indexu na více disků. Když jsou zdrojové tabulky interaktivně aktualizovány uživateli, obsah indexu spojení se automaticky aktualizuje. Jakýkoli dotaz, jehož Klauzule WHERE určuje jakoukoli kombinaci sloupců nebo výrazů sloupců, které jsou přesnou podmnožinou těch definovaných v indexu spojení (tzv. „krycí dotaz“) způsobí, že během dotazu bude konzultován index spojení, nikoli původní tabulky a jejich indexy provedení.
Implementace Oracle se omezuje na používání bitmapové indexy. A bitmapový index připojení se používá pro sloupce s nízkou mohutností (tj. sloupce obsahující méně než 300 odlišných hodnot, podle dokumentace Oracle): kombinuje sloupce s nízkou mohutností z více souvisejících tabulek. Příklad, který společnost Oracle používá, je systém zásob, kde různí dodavatelé poskytují různé součásti. The schéma má tři propojené tabulky: dvě „hlavní tabulky“, část a dodavatel a „podrobnou tabulku“, inventář. Poslední je tabulka typu mnoho k mnoha, která propojuje dodavatele s částí a obsahuje nejvíce řádků. Každá součást má typ součásti a každý dodavatel sídlí v USA a má sloupec Stav. V USA není více než 60 států a teritorií a ne více než 300 typů součástí. Index spojení bitmap je definován pomocí standardního spojení tří tabulek ve třech výše uvedených tabulkách a zadáním sloupců Part_Type a Supplier_State pro index. Je však definován v tabulce zásob, přestože sloupce Part_Type a Supplier_State jsou „vypůjčené“ od dodavatele a části.
Pokud jde o Teradata, index připojení bitmapy Oracle se používá pouze k zodpovězení dotazu, když je dotaz Klauzule WHERE určuje sloupce omezené na ty, které jsou zahrnuty v indexu spojení.
Přímé spojení
Některé databázové systémy umožňují uživateli přinutit systém číst tabulky ve spojení v určitém pořadí. Používá se, když se optimalizátor spojení rozhodne číst tabulky v neefektivním pořadí. Například v MySQL příkaz STRAIGHT_JOIN
čte tabulky přesně v pořadí uvedeném v dotazu.[15]
Viz také
Reference
Citace
- ^ SQL CROSS JOIN
- ^ Greg Robidoux, „Vyvarujte se funkcí serveru SQL Server v klauzuli WHERE o výkonu“, MSSQL Tips, 3. května 2007
- ^ Patrick Wolf, „Inside Oracle APEX“ Pozor při používání funkcí PL / SQL v příkazu SQL, 30. listopadu 2006
- ^ Gregory A. Larsen, „Osvědčené postupy T-SQL - nepoužívejte funkce skalární hodnoty v seznamu sloupců nebo klauzule WHERE“, 29. října 2009,
- ^ Zjednodušení spojení pomocí USING klíčového slova
- ^ v Unicode, symbol motýlek je ⋈ (U + 22C8).
- ^ Zeptejte se Toma "Oracle podporuje připojení ANSI." Zpět k základům: vnitřní spojení »Blog Eddieho Awada Archivováno 19. 11. 2010 na Wayback Machine
- ^ Silberschatz, Abraham; Korth, Hank; Sudarshan, S. (2002). "Oddíl 4.10.2: Typy připojení a podmínky". Koncepty databázového systému (4. vydání). p. 166. ISBN 0072283637.
- ^ Oracle opustil vnější připojení
- ^ Shah 2005, str. 165
- ^ Převzato z Pratt 2005, str. 115–6
- ^ Yu & Meng 1998, str. 213
- ^ Oracle Bitmap Join Index. URL: http://www.dba-oracle.com/art_builder_bitmap_join_idx.htm
- ^ Připojte se k indexům Teradata. „Archivovaná kopie“. Archivovány od originál dne 2012-12-16. Citováno 2012-06-14.CS1 maint: archivovaná kopie jako titul (odkaz)
- ^ „13.2.9.2 JOIN Syntax“. Referenční příručka MySQL 5.7. Oracle Corporation. Citováno 2015-12-03.
Zdroje
- Pratt, Phillip J (2005), Průvodce SQL, sedmé vydání, Technologie kurzu Thomson, ISBN 978-0-619-21674-0
- Shah, Nilesh (2005) [2002], Databázové systémy využívající Oracle - zjednodušený průvodce pro SQL a PL / SQL druhé vydání (International ed.), Pearson Education International, ISBN 0-13-191180-5
- Yu, Clement T .; Meng, Weiyi (1998), Principy zpracování databázových dotazů pro pokročilé aplikace Morgan Kaufmann, ISBN 978-1-55860-434-6, vyvoláno 2009-03-03