sql >> Databáze >  >> RDS >> PostgreSQL

Použití spojení ke kombinování dat z různých tabulek v PostgreSQL


Úvod

Rozdělení souvisejících dat do samostatných tabulek může být výhodné z hlediska konzistence, flexibility a určitých typů výkonu. Stále však potřebujete rozumný způsob opětovné integrace záznamů, když relevantní informace zahrnují více tabulek.

V relačních databázích se připojí nabízejí způsob, jak kombinovat záznamy ve dvou nebo více tabulkách na základě společných hodnot polí. Různé typy spojení mohou dosáhnout různých výsledků v závislosti na tom, jak by se mělo zacházet s neshodnými řádky. V této příručce probereme různé typy spojení, které PostgreSQL nabízí, a jak je můžete použít ke kombinaci dat tabulek z více zdrojů.



Co jsou spojení?

Stručně řečeno, připojí se představují způsob zobrazení dat z více tabulek. Dělají to spojením záznamů z různých zdrojů na základě odpovídajících hodnot v určitých sloupcích. Každý výsledný řádek se skládá ze záznamu z první tabulky kombinovaného s řádkem z druhé tabulky na základě jednoho nebo více sloupců v každé tabulce, které mají stejnou hodnotu.

Základní syntaxe spojení vypadá takto:

SELECT    *FROM    <first_table><join_type> <second_table>    <join_condition>;

Ve spojení je každý výsledný řádek vytvořen zahrnutím všech sloupců první tabulky následovaných všemi sloupci z druhé tabulky. SELECT část dotazu lze použít k určení přesných sloupců, které chcete zobrazit.

Pokud hodnoty ve sloupcích použitých pro srovnání nejsou jedinečné, lze z původních tabulek sestavit více řádků. Představte si například, že máte porovnávaný sloupec z první tabulky, který má dva záznamy s hodnotou „červená“. Tomu odpovídá sloupec z druhé tabulky, který má tři řádky s touto hodnotou. Spojení vytvoří šest různých řádků pro tuto hodnotu, které představují různé kombinace, kterých lze dosáhnout.

Typ spojení a podmínky spojení určují, jak je vytvořen každý zobrazený řádek. To má vliv na to, co se stane s řádky z každé tabulky, které se nedělají mít shodu s podmínkou připojení.

Z důvodu pohodlí mnoho spojení odpovídá primárnímu klíči na jedné tabulce s přidruženým cizím klíčem na druhé tabulce. Ačkoli primární a cizí klíče používá databázový systém pouze k zachování záruk konzistence, jejich vztah z nich často dělá vhodného kandidáta pro podmínky připojení.



Různé typy spojení

K dispozici jsou různé typy spojení, z nichž každý potenciálně poskytne jiné výsledky. Pochopení toho, jak je každý typ konstruován, vám pomůže určit, který je vhodný pro různé scénáře.


Vnitřní spojení

Výchozí spojení se nazývá vnitřní spojení . V PostgreSQL to lze zadat buď pomocí INNER JOIN nebo jednoduše JOIN .

Zde je typický příklad demonstrující syntaxi vnitřního spojení:

SELECT    *FROM    table_1[INNER] JOIN table_2    ON table_1.id = table_2.table_1_id;

Vnitřní spojení je nejvíce omezující typ spojení, protože zobrazuje pouze řádky vytvořené kombinací řádků z každé tabulky. Všechny řádky v základních tabulkách, které neměly odpovídající protějšek v druhé tabulce, jsou z výsledků odstraněny. Pokud má například první tabulka ve srovnávacím sloupci hodnotu „modrá“ a druhá tabulka nemá žádný záznam s touto hodnotou, bude tento řádek z výstupu vyřazen.

Pokud výsledky znázorníte jako Vennův diagram tabulek součástí, vnitřní spojení vám umožní znázornit překrývající se oblast dvou kruhů. Není zobrazena žádná z hodnot, které existovaly pouze v jedné z tabulek.



Připojení vlevo

Levé spojení je spojení, které zobrazuje všechny záznamy nalezené ve vnitřním spojení plus všechny nepřiřazené řádky z první tabulky. V PostgreSQL to lze zadat jako LEFT OUTER JOIN nebo jen jako LEFT JOIN .

Základní syntaxe levého spojení se řídí tímto vzorem:

SELECT    *FROM    table_1LEFT JOIN table_2    ON table_1.id = table_2.table_1_id;

Levé spojení se vytvoří tak, že se nejprve provede vnitřní spojení, aby se vytvořily řádky ze všech odpovídajících záznamů v obou tabulkách. Poté jsou zahrnuty i neporovnané záznamy z první tabulky. Protože každý řádek ve spojení obsahuje sloupce obou tabulek, neshodné sloupce používají NULL jako hodnotu pro všechny sloupce ve druhé tabulce.

Pokud výsledky znázorníte jako Vennův diagram tabulek komponent, levé spojení vám umožní znázornit celý levý kruh. Části levého kruhu představované průsečíkem mezi dvěma kruhy budou mít další údaje doplněné pravou tabulkou.



Správné připojení

Správné spojení je spojení, které zobrazuje všechny záznamy nalezené ve vnitřním spojení a všechny nepřiřazené řádky z druhé tabulky. V PostgreSQL to lze zadat jako RIGHT OUTER JOIN nebo jen jako RIGHT JOIN .

Základní syntaxe pravého spojení se řídí tímto vzorem:

SELECT    *FROM    table_1RIGHT JOIN table_2    ON table_1.id = table_2.table_1_id;

Pravé spojení je vytvořeno nejprve provedením vnitřního spojení, aby se vytvořily řádky ze všech odpovídajících záznamů v obou tabulkách. Poté jsou zahrnuty i neporovnané záznamy z druhé tabulky. Protože každý řádek ve spojení obsahuje sloupce obou tabulek, neshodné sloupce používají NULL jako hodnotu pro všechny sloupce v první tabulce.

Pokud výsledky znázorníte jako Vennův diagram tabulek komponent, pravé spojení vám umožní znázornit celý pravý kruh. Části pravého kruhu představované průsečíkem mezi dvěma kruhy budou mít další údaje doplněné levou tabulkou.



Úplné připojení

Úplné spojení je spojení, které zobrazuje všechny záznamy nalezené ve vnitřním spojení a všechny nepřiřazené řádků z obou tabulek komponent. V PostgreSQL to lze zadat jako FULL OUTER JOIN nebo jen jako FULL JOIN .

Základní syntaxe úplného spojení se řídí tímto vzorem:

SELECT    *FROM    table_1FULL JOIN table_2    ON table_1.id = table_2.table_1_id;

Úplné spojení je vytvořeno nejprve provedením vnitřního spojení, aby se vytvořily řádky ze všech odpovídajících záznamů v obou tabulkách. Následně jsou zahrnuty i nespárované záznamy z obou tabulek. Protože každý řádek ve spojení obsahuje sloupce obou tabulek, neshodné sloupce používají NULL jako hodnotu pro všechny sloupce v jiné neodpovídající tabulce.

Pokud výsledky znázorníte jako Vennův diagram tabulek součástí, úplné spojení vám umožní zcela znázornit obě kružnice součástí. Průsečík dvou kružnic bude mít hodnoty poskytnuté každou z tabulek komponent. Části kruhů mimo překrývající se oblasti budou mít hodnoty z tabulky, do které patří, pomocí NULL k vyplnění sloupců v druhé tabulce.



Křížové spojení

Speciální spojení zvané CROSS JOIN je také k dispozici. Křížové spojení nepoužívá žádná srovnání k určení, zda se řádky v každé tabulce vzájemně shodují. Místo toho jsou výsledky vytvořeny jednoduchým přidáním každého z řádků z první tabulky do každého z řádků druhé tabulky.

To vytvoří kartézský součin řádků ve dvou nebo více tabulkách. Ve skutečnosti tento styl spojení bezpodmínečně kombinuje řádky z každé tabulky. Pokud má tedy každá tabulka tři řádky, výsledná tabulka bude mít devět řádků obsahujících všechny sloupce z obou tabulek.

Pokud máte například tabulku s názvem t1 v kombinaci s tabulkou nazvanou t2 , každý s řádky r1 , r2 a r3 , výsledkem by bylo devět řádků spojených takto:

t1.r1 + t2.r1t1.r1 + t2.r2t1.r1 + t2.r3t1.r2 + t2.r1t1.r2 + t2.r2t1.r2 + t2.r3t1.r3 + t2.r1t1.r3 + t2.r2t1.r3 + t2.r3


Vlastní připojení

Vlastní spojení je jakékoli spojení, které kombinuje řádky tabulky se sebou samým. Nemusí být hned zřejmé, jak by to mohlo být užitečné, ale ve skutečnosti má mnoho společných aplikací.

Tabulky často popisují entity, které mohou ve vzájemném vztahu plnit více rolí. Například, pokud máte tabulku people , každý řádek může potenciálně obsahovat mother sloupec, který odkazuje na jiné people ve stole. Vlastní spojení by vám umožnilo spojit tyto různé řádky dohromady spojením druhé instance tabulky s první, kde se tyto hodnoty shodují.

Vzhledem k tomu, že vlastní spojení odkazují na stejnou tabulku dvakrát, jsou k odlišení odkazů vyžadovány aliasy tabulek. Ve výše uvedeném příkladu byste například mohli spojit dvě instance people tabulky pomocí aliasů people AS children a people AS mothers . Tímto způsobem můžete určit, na kterou instanci tabulky odkazujete při definování podmínek spojení.

Zde je další příklad, tentokrát představující vztahy mezi zaměstnanci a manažery:

SELECT    *FROM    people AS employeeJOIN people AS manager    ON employee.manager_id = manager.id;



Připojit se k podmínkám

Při kombinování tabulek podmínka spojení určuje, jak budou řádky spojeny dohromady, aby vytvořily složené výsledky. Základním předpokladem je definovat sloupce v každé tabulce, které se musí shodovat, aby na daném řádku došlo ke spojení.


ON klauzule

Nejstandardnějším způsobem, jak definovat podmínky pro spojení tabulek, je ON doložka. ON klauzule používá znaménko rovná se k určení přesných sloupců z každé tabulky, které budou porovnány, aby se určilo, kdy může dojít ke spojení. PostgreSQL používá poskytnuté sloupce ke spojení řádků z každé tabulky.

ON klauzule je nejpodrobnější, ale také nejflexibilnější z dostupných podmínek spojení. Umožňuje specifičnost bez ohledu na to, jak standardizované jsou názvy sloupců jednotlivých kombinovaných tabulek.

Základní syntaxe ON klauzule vypadá takto:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.ident;

Zde jsou řádky z table1 a table2 bude připojen vždy, když id sloupec z table1 odpovídá ident sloupec z table2 . Protože se používá vnitřní spojení, výsledky zobrazí pouze řádky, které byly spojeny. Protože dotaz používá zástupný znak * znak, zobrazí se všechny sloupce z obou tabulek.

To znamená, že obě id sloupec z table1 a ident sloupec z table2 se zobrazí, i když mají stejnou přesnou hodnotu na základě splnění podmínky spojení. Této duplicitě se můžete vyhnout voláním přesných sloupců, které chcete zobrazit v SELECT seznam sloupců.



USING klauzule

USING klauzule je zkratka pro specifikaci podmínek ON klauzule, kterou lze použít, když porovnávané sloupce mají v obou tabulkách stejný název. USING klauzule přebírá seznam názvů sdílených sloupců, které by měly být porovnány, uzavřený v závorkách.

Obecná syntaxe USING klauzule používá tento formát:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Toto spojení kombinuje table1 s table2 když dva sloupce, které obě tabulky sdílejí (id a state ) každý má odpovídající hodnoty.

Stejné spojení by mohlo být vyjádřeno podrobněji pomocí ON takhle:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state;

Zatímco obě výše uvedená spojení by vedla k vytvoření stejných řádků se stejnými daty, zobrazily by se mírně odlišné. Zatímco ON klauzule obsahuje všechny sloupce z obou tabulek, USING klauzule potlačí duplicitní sloupce. Takže místo toho, aby byly dvě samostatné id sloupce a dva samostatné state sloupce (jeden pro každou tabulku), výsledky by měly pouze jeden z každého sdíleného sloupce, za nímž by následovaly všechny ostatní sloupce poskytnuté table1 a table2 .



NATURAL klauzule

NATURAL klauzule je další zkratkou, která může dále snížit upovídanost USING doložka. A NATURAL join neuvádí any sloupce, které mají být spárovány. Místo toho PostgreSQL automaticky spojí tabulky na základě všech sloupců, které mají odpovídající sloupce v každé databázi.

Obecná syntaxe NATURAL spojovací klauzule vypadá takto:

SELECT    *FROM    table1NATURAL JOIN    table2;

Za předpokladu, že table1 a table2 oba mají sloupce s názvem id , state a company , výše uvedený dotaz by byl ekvivalentní tomuto dotazu pomocí ON klauzule:

SELECT    *FROM    table1JOIN    table2ON    table1.id = table2.id AND table1.state = table2.state AND table1.company = table2.company;

A tento dotaz pomocí USING klauzule:

SELECT    *FROM    table1JOIN    table2USING    (id, state, company);

Stejně jako USING klauzule, NATURAL klauzule potlačuje duplicitní sloupce, takže by ve výsledcích byla pouze jedna instance každého ze spojených sloupců.

Zatímco NATURAL klauzule může snížit upovídanost vašich dotazů, při jejím používání je třeba postupovat opatrně. Vzhledem k tomu, že sloupce použité pro spojení tabulek jsou vypočítány automaticky, pokud se sloupce v tabulkách komponent změní, výsledky se mohou značně lišit v důsledku nových podmínek spojení.




Připojit se k podmínkám a WHERE klauzule

Podmínky spojení sdílejí mnoho charakteristik s porovnáním používaným k filtrování řádků dat pomocí WHERE doložky. Oba konstrukty definují výrazy, které se musí vyhodnotit jako pravdivé, aby byl řádek uvažován. Z tohoto důvodu není vždy intuitivní, jaký je rozdíl mezi zahrnutím dalších srovnání do WHERE konstrukce versus jejich definování v samotné klauzuli spojení.

Abychom pochopili rozdíly, které z toho vyplynou, musíme se podívat na pořadí, ve kterém PostgreSQL zpracovává různé části dotazu. V tomto případě se nejprve zpracují predikáty v podmínce spojení, aby se vytvořila virtuální spojená tabulka v paměti. Po této fázi výrazy v WHERE klauzule jsou vyhodnoceny pro filtrování výsledných řádků.

Předpokládejme například, že máme dvě tabulky s názvem customer a order že se musíme spojit. Chceme spojit dvě tabulky shodou s customer.id sloupec s order.customer_id sloupec. Kromě toho nás zajímají řádky v order tabulky, které mají product_id z 12345.

Vzhledem k výše uvedeným požadavkům máme dvě podmínky, na kterých nám záleží. Způsob, jakým tyto podmínky vyjádříme, však určí výsledky, které obdržíme.

Nejprve použijme obě jako podmínky spojení pro LEFT JOIN :

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_id AND order.product_id = 12345;

Výsledky by mohly potenciálně vypadat nějak takto:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345        4380 | Acme Co  |          |         320 | Other Co |          |          20 | Early Co |          |        8033 | Big Co   |          |(7 rows)

PostgreSQL dospěl k tomuto výsledku provedením následujících operací:

  1. Zkombinujte libovolné řádky v customer tabulka s order tabulka kde:
    • customer.id odpovídá order.customer_id .
    • order.product_id odpovídá 12345
  2. Protože používáme levé spojení, zahrňte všechny nepřiřazené řádky z levé tabulky (customer ), vyplnění sloupců z pravé tabulky (order ) s NULL hodnoty.
  3. Zobrazte pouze sloupce uvedené v SELECT specifikace sloupce.

Výsledkem je, že všechny naše spojené řádky splňují obě podmínky, které hledáme. Levé spojení však způsobí, že PostgreSQL zahrne také všechny řádky z první tabulky, které nesplňují podmínku spojení. To má za následek „zbylé“ řádky, které se nezdají být v souladu se zjevným záměrem dotazu.

Pokud přesuneme druhý dotaz (order.product_id =12345) na WHERE klauzule, místo abychom ji zahrnuli jako podmínku spojení, dostaneme jiné výsledky:

SELECT    customer.id AS customer_id,    customer.name,    order.id AS order_id,    order.product_idFROM    customerLEFT JOIN    orderON    customer.id = order.customer_idWHERE    order.product_id = 12345;

Tentokrát jsou zobrazeny pouze tři řádky:

 customer_id |   name   | order_id | product_id ------------+----------+----------+------------        4380 | Acme Co  |      480 |      12345        4380 | Acme Co  |      182 |      12345         320 | Other Co |      680 |      12345(3 rows)

Důvodem těchto rozdílů je pořadí, ve kterém jsou porovnání prováděna. Tentokrát PostgreSQL zpracuje dotaz takto:

  1. Zkombinujte libovolné řádky v customer tabulka s order tabulka, kde je customer.id odpovídá order.customer_id .
  2. Protože používáme levé spojení, zahrňte všechny nepřiřazené řádky z levé tabulky (customer ), vyplnění sloupců z pravé tabulky (order ) s NULL hodnoty.
  3. Vyhodnoťte WHERE klauzule k odstranění všech řádků, které nemají 12345 jako hodnotu pro order.product_id sloupec.
  4. Zobrazte pouze sloupce uvedené v SELECT specifikace sloupce.

Tentokrát, i když používáme levé spojení, WHERE klauzule zkrátí výsledky odfiltrováním všech řádků bez správného product_id . Protože všechny neshodné řádky by měly product_id nastavte na NULL , tím se odstraní všechny neodpovídající řádky, které byly vyplněny levým spojením. Odstraní také všechny řádky, které odpovídaly podmínce spojení a které neprošly tímto druhým kolem kontrol.

Pochopení základního procesu, který PostgreSQL používá k provádění vašich dotazů, vám může pomoci vyhnout se některým snadno proveditelným, ale obtížně laditelným chybám při práci s vašimi daty.



Závěr

V této příručce jsme se zabývali tím, jak spojení umožňují relačním databázím kombinovat data z různých tabulek a poskytovat tak hodnotnější odpovědi. Mluvili jsme o různých spojeních, která PostgreSQL podporuje, o způsobu, jakým každý typ sestavuje své výsledky, a o tom, co lze očekávat při použití konkrétních druhů spojení. Poté jsme prošli různými způsoby, jak definovat podmínky spojení, a podívali jsme se na souhru mezi spojeními a WHERE klauzule může vést k překvapením.

Spojení jsou nezbytnou součástí toho, co dělá relační databáze dostatečně výkonnými a flexibilními, aby zvládly tolik různých typů dotazů. Uspořádání dat pomocí logických hranic a přitom stále možnost rekombinovat data novými způsoby případ od případu dává relačním databázím, jako je PostgreSQL, neuvěřitelnou všestrannost. Naučíte-li se, jak provádět toto spojování mezi tabulkami, umožní vám vytvářet složitější dotazy a spoléhat se na databázi při vytváření úplných obrázků vašich dat.




  1. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:Selhání komunikačního spojení

  2. Vytvořte tabulku dvou typů v PostgreSQL

  3. SqlBulkCopy ze seznamu<>

  4. Jak povolit pomalé dotazy MySQL Přihlaste se do MySQL