sql >> Database teknologi >  >> RDS >> PostgreSQL

Brug af joinforbindelser til at kombinere data fra forskellige tabeller i PostgreSQL


Introduktion

At opdele relaterede data i separate tabeller kan være fordelagtigt ud fra et synspunkt om sammenhæng, fleksibilitet og visse typer ydeevne. Du har dog stadig brug for en rimelig måde at genintegrere poster på, når de relevante oplysninger strækker sig over flere tabeller.

I relationsdatabaser joins tilbyde en måde at kombinere posterne i to eller flere tabeller baseret på fælles feltværdier. Forskellige typer sammenføjninger kan opnå forskellige resultater afhængigt af, hvordan umatchede rækker skal håndteres. I denne guide vil vi diskutere de forskellige typer joins, som PostgreSQL tilbyder, og hvordan du kan bruge dem til at kombinere tabeldata fra flere kilder.



Hvad er joinforbindelser?

Kort sagt, tilslutter sig er en måde at vise data fra flere tabeller på. Det gør de ved at sammenføje poster fra forskellige kilder baseret på matchende værdier i bestemte kolonner. Hver resulterende række består af en post fra den første tabel kombineret med en række fra den anden tabel, baseret på en eller flere kolonner i hver tabel med samme værdi.

Den grundlæggende syntaks for en join ser således ud:

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

I en joinforbindelse er hver resulterende række konstrueret ved at inkludere alle kolonnerne i den første tabel efterfulgt af alle kolonnerne fra den anden tabel. SELECT del af forespørgslen kan bruges til at angive de nøjagtige kolonner, du ønsker at vise.

Flere rækker kan konstrueres ud fra de originale tabeller, hvis værdierne i kolonnerne, der bruges til sammenligning, ikke er unikke. Forestil dig for eksempel, at du har en kolonne, der sammenlignes fra den første tabel, som har to poster med værdien "rød". Matchet med dette er en kolonne fra den anden tabel, der har tre rækker med den værdi. Sammenføjningen vil producere seks forskellige rækker for den værdi, der repræsenterer de forskellige kombinationer, der kan opnås.

Sammenkædningstypen og sammenkædningsbetingelserne bestemmer, hvordan hver række, der vises, er opbygget. Dette påvirker, hvad der sker med rækkerne fra hver tabel, der gør og ikke gør har en match på join-betingelsen.

For nemheds skyld matcher mange joins den primære nøgle på den ene tabel med en tilknyttet fremmednøgle på den anden tabel. Selvom primære og fremmede nøgler kun bruges af databasesystemet til at opretholde konsistensgarantier, gør deres forhold dem ofte til en god kandidat for tilslutningsbetingelser.



Forskellige typer joins

Forskellige typer sammenføjninger er tilgængelige, som hver især vil give forskellige resultater. At forstå, hvordan hver type er konstrueret, hjælper dig med at afgøre, hvilken der er passende til forskellige scenarier.


Indre joinforbindelse

Standardsammenføjningen kaldes en indre joinforbindelse . I PostgreSQL kan dette angives med enten INNER JOIN eller bare JOIN .

Her er et typisk eksempel, der viser syntaksen for en indre joinforbindelse:

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

En indre joinforbindelse er den mest restriktive type joinforbindelse, fordi den kun viser rækker oprettet ved at kombinere rækker fra hver tabel. Alle rækker i de konstituerende tabeller, der ikke havde en matchende modstykke i den anden tabel, fjernes fra resultaterne. Hvis den første tabel f.eks. har en værdi på "blå" i sammenligningskolonnen, og den anden tabel ikke har nogen registrering med den værdi, vil denne række blive undertrykt fra outputtet.

Hvis du repræsenterer resultaterne som et Venn-diagram af komponenttabellerne, giver en indre sammenføjning dig mulighed for at repræsentere det overlappende område af de to cirkler. Ingen af ​​de værdier, der kun fandtes i en af ​​tabellerne, vises.



Venstre joinforbindelse

En venstre joinforbindelse er en joinforbindelse, der viser alle de poster, der findes i en indre joinforbindelse, plus alle de umatchede rækker fra den første tabel. I PostgreSQL kan dette angives som en LEFT OUTER JOIN eller som bare en LEFT JOIN .

Den grundlæggende syntaks for en venstre join følger dette mønster:

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

En venstre join konstrueres ved først at udføre en indre join for at konstruere rækker fra alle de matchende poster i begge tabeller. Bagefter er de uovertrufne poster fra det første bord også inkluderet. Da hver række i en joinforbindelse inkluderer kolonnerne i begge tabeller, bruger de umatchede kolonner NULL som værdien for alle kolonnerne i den anden tabel.

Hvis du repræsenterer resultaterne som et Venn-diagram af komponenttabellerne, giver en venstre sammenføjning dig mulighed for at repræsentere hele den venstre cirkel. De dele af den venstre cirkel repræsenteret af skæringspunktet mellem de to cirkler vil have yderligere data suppleret med den højre tabel.



Højre joinforbindelse

En højre joinforbindelse er en joinforbindelse, der viser alle de poster, der findes i en indre joinforbindelse, plus alle de umatchede rækker fra den anden tabel. I PostgreSQL kan dette angives som en RIGHT OUTER JOIN eller som bare en RIGHT JOIN .

Den grundlæggende syntaks for en højre join følger dette mønster:

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

En højre join konstrueres ved først at udføre en indre join for at konstruere rækker fra alle de matchende poster i begge tabeller. Bagefter er de umatchede poster fra den anden tabel også inkluderet. Da hver række i en joinforbindelse inkluderer kolonnerne i begge tabeller, bruger de umatchede kolonner NULL som værdien for alle kolonnerne i den første tabel.

Hvis du repræsenterer resultaterne som et Venn-diagram af komponenttabellerne, giver en højresammenføjning dig mulighed for at repræsentere hele den højre cirkel. De dele af den højre cirkel repræsenteret af skæringspunktet mellem de to cirkler vil have yderligere data suppleret med den venstre tabel.



Fuld deltagelse

En fuld joinforbindelse er en joinforbindelse, der viser alle de poster, der findes i en indre joinforbindelse, plus alle de umatchede rækker fra begge komponenttabeller. I PostgreSQL kan dette angives som en FULL OUTER JOIN eller som bare en FULL JOIN .

Den grundlæggende syntaks for en fuld join følger dette mønster:

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

En fuld join konstrueres ved først at udføre en indre join for at konstruere rækker fra alle de matchende poster i begge tabeller. Bagefter er de uovertrufne poster fra begge tabeller også inkluderet. Da hver række i en joinforbindelse inkluderer kolonnerne i begge tabeller, bruger de umatchede kolonner NULL som værdien for alle kolonnerne i den umatchede anden tabel.

Hvis du repræsenterer resultaterne som et Venn-diagram over komponenttabellerne, giver en fuld sammenføjning dig mulighed for at repræsentere begge komponentcirklerne fuldstændigt. Skæringspunktet mellem de to cirkler vil have værdier leveret af hver af komponenttabellerne. Delene af cirklerne uden for det overlappende område vil have værdierne fra den tabel, de tilhører, ved hjælp af NULL for at udfylde kolonnerne i den anden tabel.



Cross join

En speciel join kaldet en CROSS JOIN er også tilgængelig. En krydssammenføjning bruger ingen sammenligninger til at bestemme, om rækkerne i hver tabel matcher hinanden. I stedet konstrueres resultater ved blot at tilføje hver af rækkerne fra den første tabel til hver af rækkerne i den anden tabel.

Dette giver et kartesisk produkt af rækkerne i to eller flere tabeller. I realiteten kombinerer denne sammenføjningsstil rækker fra hver tabel ubetinget. Så hvis hver tabel har tre rækker, ville den resulterende tabel have ni rækker indeholdende alle kolonnerne fra begge tabeller.

For eksempel, hvis du har en tabel kaldet t1 kombineret med en tabel kaldet t2 , hver med rækker r1 , r2 og r3 , ville resultatet være ni rækker kombineret således:

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


Tilmeld dig selv

En selvsammenføjning er enhver forbindelse, der kombinerer rækkerne i en tabel med sig selv. Det er måske ikke umiddelbart tydeligt, hvordan dette kunne være nyttigt, men det har faktisk mange almindelige applikationer.

Ofte beskriver tabeller enheder, der kan udfylde flere roller i forhold til hinanden. For eksempel, hvis du har en tabel med people , kan hver række potentielt indeholde en mother kolonne, der refererer til andre people i bordet. En selvsammenføjning ville give dig mulighed for at sy disse forskellige rækker sammen ved at forbinde en anden forekomst af tabellen med den første, hvor disse værdier matcher.

Da self joins refererer til den samme tabel to gange, kræves tabelaliaser for at gøre referencerne uentydige. I eksemplet ovenfor kan du f.eks. forbinde de to forekomster af people tabel ved hjælp af aliasserne people AS children og people AS mothers . På den måde kan du angive, hvilken forekomst af tabellen, du henviser til, når du definerer joinbetingelser.

Her er endnu et eksempel, som denne gang repræsenterer forholdet mellem medarbejdere og ledere:

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



Forbindelsesbetingelser

Når du kombinerer tabeller, bestemmer sammenføjningsbetingelsen, hvordan rækker matches sammen for at danne de sammensatte resultater. Den grundlæggende forudsætning er at definere de kolonner i hver tabel, der skal matche, for at sammenføjningen kan forekomme i den pågældende række.


ON klausul

Den mest standard måde at definere betingelserne for tabelsammenføjninger på er med ON klausul. ON klausul bruger et lighedstegn til at angive de nøjagtige kolonner fra hver tabel, der vil blive sammenlignet for at bestemme, hvornår en joinforbindelse kan forekomme. PostgreSQL bruger de medfølgende kolonner til at sy rækkerne fra hver tabel sammen.

ON klausul er den mest udførlige, men også den mest fleksible af de tilgængelige joinbetingelser. Det giver mulighed for specificitet, uanset hvor standardiserede kolonnenavnene er for hver tabel, der kombineres.

Den grundlæggende syntaks for ON klausul ser sådan ud:

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

Her er rækkerne fra table1 og table2 vil blive tilsluttet hver gang id kolonne fra table1 matcher ident kolonne fra table2 . Fordi der bruges en indre sammenføjning, vil resultaterne kun vise de rækker, der blev sammenføjet. Da forespørgslen bruger jokertegnet * tegn, vil alle kolonnerne fra begge tabeller blive vist.

Det betyder, at både id kolonne fra table1 og ident kolonne fra table2 vil blive vist, selvom de har den samme nøjagtige værdi i kraft af at de opfylder join-betingelsen. Du kan undgå denne duplikering ved at kalde de nøjagtige kolonner, du ønsker at vise i SELECT kolonneliste.



USING klausul

USING klausul er en forkortelse for at specificere betingelserne for en ON klausul, der kan bruges, når de kolonner, der sammenlignes, har samme navn i begge tabeller. USING klausul tager en liste, omsluttet i parentes, over de delte kolonnenavne, der skal sammenlignes.

Den generelle syntaks for USING klausul bruger dette format:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Denne join kombinerer table1 med table2 når to kolonner, som begge tabeller deler (id og state ) hver har matchende værdier.

Den samme sammenføjning kunne udtrykkes mere detaljeret ved at bruge ON sådan her:

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

Selvom begge ovenstående sammenføjninger ville resultere i, at de samme rækker blev konstrueret med de samme data til stede, ville de blive vist lidt anderledes. Mens ON klausulen inkluderer alle kolonnerne fra begge tabeller, USING klausul undertrykker de duplikerede kolonner. Så i stedet for at der er to separate id kolonner og to separate state kolonner (en for hver tabel), ville resultaterne kun have en af ​​hver af de delte kolonner, efterfulgt af alle de andre kolonner, der er leveret af table1 og table2 .



Den NATURAL klausul

Den NATURAL klausul er endnu en stenografi, der yderligere kan reducere omfanget af USING klausul. En NATURAL join specificerer ikke nogle kolonner, der skal matches. I stedet vil PostgreSQL automatisk slutte sig til tabellerne baseret på alle kolonner, der har matchende kolonner i hver database.

Den generelle syntaks for NATURAL join-klausulen ser sådan ud:

SELECT    *FROM    table1NATURAL JOIN    table2;

Forudsat at table1 og table2 begge har kolonner med navnet id , state , og company , ville ovenstående forespørgsel svare til denne forespørgsel ved at bruge ON klausul:

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

Og denne forespørgsel ved hjælp af USING klausul:

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

Ligesom USING klausulen, NATURAL klausul undertrykker duplikerede kolonner, så der ville kun være en enkelt forekomst af hver af de sammenføjede kolonner i resultaterne.

Mens NATURAL klausul kan reducere omfanget af dine forespørgsler, skal der udvises forsigtighed, når du bruger det. Fordi de kolonner, der bruges til at forbinde tabellerne, beregnes automatisk, hvis kolonnerne i komponenttabellerne ændres, kan resultaterne være vidt forskellige på grund af nye sammenføjningsbetingelser.




Forbindelsesbetingelser og WHERE klausul

Sammenføjningsbetingelser deler mange karakteristika med sammenligninger, der bruges til at filtrere rækker af data ved hjælp af WHERE klausuler. Begge konstruktioner definerer udtryk, der skal evalueres til sande, for at rækken kan tages i betragtning. På grund af dette er det ikke altid intuitivt, hvad forskellen er mellem at inkludere yderligere sammenligninger i en WHERE konstruktion kontra at definere dem i selve join-klausulen.

For at forstå de forskelle, der vil resultere, er vi nødt til at se på den rækkefølge, hvori PostgreSQL behandler forskellige dele af en forespørgsel. I dette tilfælde behandles prædikaterne i join-betingelsen først for at konstruere den virtuelle sammenføjede tabel i hukommelsen. Efter dette trin vil udtrykkene i WHERE klausul evalueres for at filtrere de resulterende rækker.

Antag som et eksempel, at vi har to tabeller kaldet customer og order at vi skal slutte os sammen. Vi ønsker at forbinde de to tabeller ved at matche customer.id kolonne med order.customer_id kolonne. Derudover er vi interesserede i rækkerne i order tabel, der har et product_id af 12345.

På baggrund af ovenstående krav har vi to forhold, som vi bekymrer os om. Den måde, vi udtrykker disse betingelser på, vil imidlertid afgøre, hvilke resultater vi modtager.

Lad os først bruge begge som joinbetingelser for 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;

Resultaterne kunne potentielt se nogenlunde sådan her ud:

 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 nåede frem til dette resultat ved at udføre følgende handlinger:

  1. Kombiner alle rækker i customer tabel med order tabel hvor:
    • customer.id matcher order.customer_id .
    • order.product_id matcher 12345
  2. Fordi vi bruger en venstre joinforbindelse, skal du inkludere alle umatchede rækker fra den venstre tabel (customer ), udfyldning af kolonnerne fra den højre tabel (order ) med NULL værdier.
  3. Vis kun de kolonner, der er angivet i SELECT kolonnespecifikation.

Resultatet er, at alle vores samlede rækker matcher begge de betingelser, som vi leder efter. Den venstre join bevirker dog, at PostgreSQL også inkluderer alle rækker fra den første tabel, der ikke opfyldte join-betingelsen. Dette resulterer i "tilbageværende" rækker, der ikke ser ud til at følge den tilsyneladende hensigt med forespørgslen.

Hvis vi flytter den anden forespørgsel (order.product_id =12345) til en WHERE klausul, i stedet for at inkludere det som en joinbetingelse, får vi forskellige resultater:

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;

Denne gang vises kun tre rækker:

 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 rækkefølge, som sammenligningerne udføres i, er årsagen til disse forskelle. Denne gang behandler PostgreSQL forespørgslen sådan her:

  1. Kombiner alle rækker i customer tabel med order tabel hvor customer.id matcher order.customer_id .
  2. Fordi vi bruger en venstre joinforbindelse, skal du inkludere alle umatchede rækker fra den venstre tabel (customer ), udfyldning af kolonnerne fra den højre tabel (order ) med NULL værdier.
  3. Evaluer WHERE klausul for at fjerne alle rækker, der ikke har 12345 som værdien for order.product_id kolonne.
  4. Vis kun de kolonner, der er angivet i SELECT kolonnespecifikation.

Denne gang, selvom vi bruger en venstre join, er WHERE klausul trunkerer resultaterne ved at bortfiltrere alle rækkerne uden det korrekte product_id . Fordi alle umatchede rækker ville have product_id indstillet til NULL , fjerner dette alle de umatchede rækker, der blev udfyldt af den venstre joinforbindelse. Det fjerner også enhver af rækkerne, der blev matchet af join-betingelsen, som ikke bestod denne anden runde af kontroller.

At forstå den grundlæggende proces, som PostgreSQL bruger til at udføre dine forespørgsler, kan hjælpe dig med at undgå nogle nemme at lave, men svære at fejlfinde, mens du arbejder med dine data.



Konklusion

I denne vejledning dækkede vi, hvordan joinforbindelser gør det muligt for relationelle databaser at kombinere data fra forskellige tabeller for at give mere værdifulde svar. Vi talte om de forskellige joinforbindelser, som PostgreSQL understøtter, den måde, hver type samler sine resultater på, og hvad man kan forvente, når man bruger specifikke typer joins. Bagefter gennemgik vi forskellige måder at definere joinbetingelser på og så på, hvordan samspillet mellem joins og WHERE klausul kan føre til overraskelser.

Joins er en væsentlig del af det, der gør relationsdatabaser kraftfulde og fleksible nok til at håndtere så mange forskellige typer forespørgsler. Organisering af data ved hjælp af logiske grænser, mens du stadig er i stand til at rekombinere dataene på nye måder fra sag til sag, giver relationelle databaser som PostgreSQL en utrolig alsidighed. At lære, hvordan du udfører denne sammensætning mellem tabeller, vil give dig mulighed for at oprette mere komplekse forespørgsler og stole på, at databasen skaber komplette billeder af dine data.




  1. Hvad er LEN()-ækvivalenten i MySQL?

  2. SQL Server 2016 på Linux

  3. WHERE IS NULL, IS NOT NULL eller NO WHERE-sætning afhængigt af SQL Server-parameterværdien

  4. Hvordan skal jeg overføre et tabelnavn til en lagret proc?