sql >> Databasteknik >  >> RDS >> PostgreSQL

Använda joins för att kombinera data från olika tabeller i PostgreSQL


Introduktion

Att dela upp relaterade data i separata tabeller kan vara fördelaktigt med tanke på konsekvens, flexibilitet och vissa typer av prestanda. Men du behöver fortfarande ett rimligt sätt att återintegrera poster när den relevanta informationen spänner över flera tabeller.

I relationsdatabaser joins erbjuda ett sätt att kombinera posterna i två eller flera tabeller baserat på vanliga fältvärden. Olika typer av kopplingar kan ge olika resultat beroende på hur omatchade rader ska hanteras. I den här guiden kommer vi att diskutera de olika typerna av anslutningar som PostgreSQL erbjuder och hur du kan använda dem för att kombinera tabelldata från flera källor.



Vad är joins?

Kort sagt, ansluter sig är ett sätt att visa data från flera tabeller. De gör detta genom att sy ihop poster från olika källor baserat på matchande värden i vissa kolumner. Varje resulterande rad består av en post från den första tabellen kombinerad med en rad från den andra tabellen, baserat på en eller flera kolumner i varje tabell som har samma värde.

Den grundläggande syntaxen för en join ser ut så här:

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

I en koppling konstrueras varje resulterande rad genom att inkludera alla kolumner i den första tabellen följt av alla kolumner från den andra tabellen. SELECT en del av frågan kan användas för att ange exakt de kolumner du vill visa.

Flera rader kan konstrueras från de ursprungliga tabellerna om värdena i kolumnerna som används för jämförelse inte är unika. Tänk dig till exempel att du har en kolumn som jämförs från den första tabellen som har två poster med värdet "rött". Matchad med detta är en kolumn från den andra tabellen som har tre rader med det värdet. Sammanfogningen kommer att producera sex olika rader för det värdet som representerar de olika kombinationer som kan uppnås.

Typen av sammanfogning och sammanfogningsvillkoren avgör hur varje rad som visas är konstruerad. Detta påverkar vad som händer med raderna från varje tabell som gör och inte ha en matchning på anslutningsvillkoret.

För enkelhetens skull matchar många anslutningar primärnyckeln på en tabell med en tillhörande främmande nyckel på den andra bordet. Även om primära och främmande nycklar endast används av databassystemet för att upprätthålla konsistensgarantier, gör deras relation dem ofta till en bra kandidat för anslutningsvillkor.



Olika typer av sammanfogningar

Olika typer av kopplingar finns tillgängliga, som var och en kan ge olika resultat. Att förstå hur varje typ är konstruerad hjälper dig att avgöra vilken som är lämplig för olika scenarier.


Inre koppling

Standardkopplingen kallas en inre koppling . I PostgreSQL kan detta specificeras med antingen INNER JOIN eller bara JOIN .

Här är ett typiskt exempel som visar syntaxen för en inre koppling:

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

En inre koppling är den mest restriktiva typen av koppling eftersom den bara visar rader skapade genom att kombinera rader från varje tabell. Alla rader i de ingående tabellerna som inte hade en matchande motsvarighet i den andra tabellen tas bort från resultaten. Till exempel, om den första tabellen har värdet "blått" i jämförelsekolumnen och den andra tabellen inte har någon post med det värdet, kommer den raden att undertryckas från utdata.

Om du representerar resultaten som ett Venn-diagram av komponenttabellerna, låter en inre koppling dig representera den överlappande arean av de två cirklarna. Inget av värden som bara fanns i en av tabellerna visas.



Vänster gå med

En vänsterkoppling är en koppling som visar alla poster som finns i en inre koppling, plus alla omatchade rader från den första tabellen. I PostgreSQL kan detta anges som en LEFT OUTER JOIN eller som bara en LEFT JOIN .

Grundsyntaxen för en vänsterkoppling följer detta mönster:

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

En vänsterkoppling konstrueras genom att först utföra en inre koppling för att konstruera rader från alla matchande poster i båda tabellerna. Efteråt ingår även de omatchade posterna från det första bordet. Eftersom varje rad i en koppling inkluderar kolumnerna i båda tabellerna använder de omatchade kolumnerna NULL som värde för alla kolumner i den andra tabellen.

Om du representerar resultaten som ett Venn-diagram av komponenttabellerna, låter en vänsterkoppling dig representera hela den vänstra cirkeln. Delarna av den vänstra cirkeln som representeras av skärningspunkten mellan de två cirklarna kommer att ha ytterligare data kompletterad med den högra tabellen.



Högeranslutning

En högerkoppling är en koppling som visar alla poster som finns i en inre koppling, plus alla omatchade rader från den andra tabellen. I PostgreSQL kan detta anges som en RIGHT OUTER JOIN eller som bara en RIGHT JOIN .

Grundsyntaxen för en högerkoppling följer detta mönster:

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

En högerkoppling konstrueras genom att först utföra en inre koppling för att konstruera rader från alla matchande poster i båda tabellerna. Efteråt ingår även de omatchade posterna från den andra tabellen. Eftersom varje rad i en koppling inkluderar kolumnerna i båda tabellerna använder de omatchade kolumnerna NULL som värdet för alla kolumner i den första tabellen.

Om du representerar resultaten som ett Venn-diagram av komponenttabellerna, låter en högerkoppling dig representera hela den högra cirkeln. Delarna av den högra cirkeln som representeras av skärningspunkten mellan de två cirklarna kommer att ha ytterligare data kompletterade med den vänstra tabellen.



Fullständig koppling

En fullständig koppling är en koppling som visar alla poster som finns i en inre koppling, plus alla omatchade rader från båda komponenttabellerna. I PostgreSQL kan detta anges som en FULL OUTER JOIN eller som bara en FULL JOIN .

Grundsyntaxen för en fullständig koppling följer detta mönster:

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

En fullständig koppling konstrueras genom att först utföra en inre koppling för att konstruera rader från alla matchande poster i båda tabellerna. Efteråt ingår även de omatchade posterna från båda tabellerna. Eftersom varje rad i en koppling inkluderar kolumnerna i båda tabellerna använder de omatchade kolumnerna NULL som värdet för alla kolumner i den omatchade andra tabellen.

Om du representerar resultaten som ett Venn-diagram av komponenttabellerna, låter en fullständig sammanfogning dig representera båda komponentcirklarna helt och hållet. Skärningspunkten mellan de två cirklarna kommer att ha värden som tillhandahålls av var och en av komponenttabellerna. Delarna av cirklarna utanför det överlappande området kommer att ha värdena från tabellen de tillhör, med NULL för att fylla i kolumnerna som finns i den andra tabellen.



Cross join

En speciell koppling som kallas CROSS JOIN finns också tillgänglig. En korskoppling använder inga jämförelser för att avgöra om raderna i varje tabell matchar varandra. Istället konstrueras resultaten genom att helt enkelt lägga till var och en av raderna från den första tabellen till var och en av raderna i den andra tabellen.

Detta ger en kartesisk produkt av raderna i två eller flera tabeller. I själva verket kombinerar denna kopplingsstil rader från varje tabell utan villkor. Så om varje tabell har tre rader, skulle den resulterande tabellen ha nio rader som innehåller alla kolumner från båda tabellerna.

Till exempel, om du har en tabell som heter t1 kombinerat med en tabell som heter t2 , var och en med rader r1 , r2 och r3 , skulle resultatet bli nio rader kombinerade så här:

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


Gå med själv

En självkoppling är vilken koppling som helst som kombinerar raderna i en tabell med sig själv. Det kanske inte är direkt uppenbart hur detta kan vara användbart, men det har faktiskt många vanliga applikationer.

Ofta beskriver tabeller enheter som kan fylla flera roller i förhållande till varandra. Till exempel, om du har en tabell med people , kan varje rad eventuellt innehålla en mother kolumn som refererar till andra people i bordet. En självkoppling skulle tillåta dig att sy ihop dessa olika rader genom att koppla en andra instans av tabellen till den första där dessa värden matchar.

Eftersom self joins refererar till samma tabell två gånger, krävs tabellalias för att disambiguera referenserna. I exemplet ovan kan du till exempel slå samman de två instanserna av people tabell med aliasen people AS children och people AS mothers . På så sätt kan du ange vilken instans av tabellen du hänvisar till när du definierar anslutningsvillkor.

Här är ett annat exempel, den här gången som representerar relationer mellan anställda och chefer:

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



Anslutningsvillkor

När du kombinerar tabeller avgör kopplingsvillkoret hur rader matchas för att bilda de sammansatta resultaten. Grundförutsättningen är att definiera de kolumner i varje tabell som måste matcha för att sammanfogningen ska ske på den raden.


ON klausul

Det vanligaste sättet att definiera villkoren för tabellkopplingar är med ON klausul. ON sats använder ett likhetstecken för att specificera exakta kolumner från varje tabell som kommer att jämföras för att avgöra när en koppling kan inträffa. PostgreSQL använder de medföljande kolumnerna för att sy ihop raderna från varje tabell.

ON satsen är den mest utförliga, men också den mest flexibla av de tillgängliga anslutningsvillkoren. Det möjliggör specificitet oavsett hur standardiserade kolumnnamnen är för varje tabell som kombineras.

Den grundläggande syntaxen för ON klausul ser ut så här:

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

Här är raderna från table1 och table2 kommer att anslutas när id kolumn från table1 matchar ident kolumn från table2 . Eftersom en inre koppling används kommer resultaten bara att visa de rader som anslutits. Eftersom frågan använder jokertecknet * tecken, kommer alla kolumner från båda tabellerna att visas.

Detta betyder att både id kolumn från table1 och ident kolumn från table2 kommer att visas, även om de har samma exakta värde i kraft av att de uppfyller kopplingsvillkoret. Du kan undvika denna dubblering genom att anropa exakt de kolumner du vill visa i SELECT kolumnlista.



USING klausul

USING sats är en förkortning för att specificera villkoren för en ON sats som kan användas när kolumnerna som jämförs har samma namn i båda tabellerna. USING sats tar en lista, omgiven inom parentes, över de delade kolumnnamn som ska jämföras.

Den allmänna syntaxen för USING klausul använder detta format:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Denna koppling kombinerar table1 med table2 när två kolumner som båda tabellerna delar (id och state ) alla har matchande värden.

Samma koppling skulle kunna uttryckas mer utförligt med ON så här:

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

Även om båda ovanstående kopplingar skulle resultera i att samma rader konstruerades med samma data närvarande, skulle de visas något annorlunda. Medan ON satsen inkluderar alla kolumner från båda tabellerna, USING sats undertrycker dubblettkolumnerna. Så istället för att det finns två separata id kolumner och två separata state kolumner (en för varje tabell), skulle resultaten bara ha en av var och en av de delade kolumnerna, följt av alla andra kolumner som tillhandahålls av table1 och table2 .



Den NATURAL klausul

Den NATURAL satsen är ytterligare en förkortning som ytterligare kan minska utförligheten av USING klausul. En NATURAL join anger inte någon kolumner som ska matchas. Istället kommer PostgreSQL automatiskt att sammanfoga tabellerna baserat på alla kolumner som har matchande kolumner i varje databas.

Den allmänna syntaxen för NATURAL join-satsen ser ut så här:

SELECT    *FROM    table1NATURAL JOIN    table2;

Förutsatt att table1 och table2 båda har kolumner med namnet id , state och company , skulle ovanstående fråga vara likvärdig med den här frågan med ON klausul:

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

Och den här frågan använder USING klausul:

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

Som USING satsen, NATURAL sats undertrycker dubbletter av kolumner, så det skulle bara finnas en enda instans av var och en av de sammanfogade kolumnerna i resultaten.

Medan NATURAL klausulen kan minska innehållet i dina frågor, måste försiktighet iakttas när du använder den. Eftersom kolumnerna som används för att sammanfoga tabellerna beräknas automatiskt, om kolumnerna i komponenttabellerna ändras, kan resultaten bli mycket annorlunda på grund av nya sammanfogningsvillkor.




Anslutningsvillkor och WHERE klausul

Anslutningsvillkor delar många egenskaper med jämförelserna som används för att filtrera rader med data med WHERE klausuler. Båda konstruktionerna definierar uttryck som måste utvärderas till sanna för att raden ska beaktas. På grund av detta är det inte alltid intuitivt vad skillnaden är mellan att inkludera ytterligare jämförelser i en WHERE konstruktion kontra att definiera dem inom join-satsen själv.

För att förstå skillnaderna som kommer att resultera, måste vi ta en titt på i vilken ordning PostgreSQL behandlar olika delar av en fråga. I detta fall bearbetas predikaten i sammanfogningsvillkoret först för att konstruera den virtuella sammanfogade tabellen i minnet. Efter detta steg visas uttrycken i WHERE satsen utvärderas för att filtrera de resulterande raderna.

Anta som ett exempel att vi har två tabeller som heter customer och order att vi behöver gå samman. Vi vill sammanfoga de två tabellerna genom att matcha customer.id kolumnen med order.customer_id kolumn. Dessutom är vi intresserade av raderna i order tabell som har ett product_id av 12345.

Med tanke på ovanstående krav har vi två villkor som vi bryr oss om. Sättet vi uttrycker dessa villkor på kommer dock att avgöra vilka resultat vi får.

Låt oss först använda båda som anslutningsvillkor för en 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;

Resultaten kan potentiellt se ut ungefär så här:

 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 kom fram till detta resultat genom att utföra följande operationer:

  1. Kombinera alla rader i customer tabell med order tabell där:
    • customer.id matchar order.customer_id .
    • order.product_id matchar 12345
  2. Eftersom vi använder en vänsterkoppling, inkludera eventuella omatchade rader från den vänstra tabellen (customer ), fylla ut kolumnerna från den högra tabellen (order ) med NULL värden.
  3. Visa endast kolumnerna som anges i SELECT kolumnspecifikation.

Resultatet är att alla våra sammanfogade rader matchar båda villkoren som vi letar efter. Den vänstra kopplingen gör dock att PostgreSQL även inkluderar alla rader från den första tabellen som inte uppfyllde kopplingsvillkoret. Detta resulterar i "överblivna" rader som inte verkar följa den uppenbara avsikten med frågan.

Om vi ​​flyttar den andra frågan (order.product_id =12345) till en WHERE i stället för att inkludera det som ett kopplingsvillkor, får vi olika resultat:

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;

Den här gången visas endast tre rader:

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

Den ordning i vilken jämförelserna utförs är orsaken till dessa skillnader. Den här gången bearbetar PostgreSQL frågan så här:

  1. Kombinera alla rader i customer tabell med order tabell där customer.id matchar order.customer_id .
  2. Eftersom vi använder en vänsterkoppling, inkludera eventuella omatchade rader från den vänstra tabellen (customer ), fylla ut kolumnerna från den högra tabellen (order ) med NULL värden.
  3. Utvärdera WHERE sats för att ta bort alla rader som inte har 12345 som värde för order.product_id kolumn.
  4. Visa endast kolumnerna som anges i SELECT kolumnspecifikation.

Den här gången, även om vi använder en vänsteranslutning, WHERE klausul trunkerar resultaten genom att filtrera bort alla rader utan korrekt product_id . Eftersom alla omatchade rader skulle ha product_id inställd på NULL , detta tar bort alla omatchade rader som fylldes i av den vänstra kopplingen. Den tar också bort alla rader som matchades av anslutningsvillkoret som inte klarade den här andra omgången av kontroller.

Att förstå den grundläggande processen som PostgreSQL använder för att köra dina frågor kan hjälpa dig att undvika en del lätta att göra men svårfelsökta misstag när du arbetar med din data.



Slutsats

I den här guiden behandlade vi hur kopplingar gör det möjligt för relationsdatabaser att kombinera data från olika tabeller för att ge mer värdefulla svar. Vi pratade om de olika joins som PostgreSQL stöder, hur varje typ sammanställer sina resultat och vad man kan förvänta sig när man använder specifika typer av joins. Efteråt gick vi över olika sätt att definiera kopplingsvillkor och tittade på hur samspelet mellan kopplingar och WHERE klausul kan leda till överraskningar.

Joins är en viktig del av det som gör relationsdatabaser kraftfulla och flexibla nog att hantera så många olika typer av frågor. Att organisera data med logiska gränser samtidigt som man fortfarande kan kombinera data på nya sätt från fall till fall ger relationsdatabaser som PostgreSQL otrolig mångsidighet. Genom att lära dig hur du utför denna sammanfogning mellan tabeller kan du skapa mer komplexa frågor och lita på att databasen skapar kompletta bilder av dina data.




  1. Group_concat MySQL-funktionens motsvarighet i Oracle

  2. SQLite MIN

  3. Multitenancy-alternativ för PostgreSQL

  4. Importera filer i Oracle Apex med wwv_flow_files