sql >> Database >  >> RDS >> PostgreSQL

Joins gebruiken om gegevens uit verschillende tabellen te combineren in PostgreSQL


Inleiding

Het splitsen van gerelateerde gegevens in afzonderlijke tabellen kan gunstig zijn vanuit het oogpunt van consistentie, flexibiliteit en bepaalde soorten prestaties. U hebt echter nog steeds een redelijke manier nodig om records opnieuw te integreren wanneer de relevante informatie meerdere tabellen omvat.

In relationele databases, wordt lid bieden een manier om de records in twee of meer tabellen te combineren op basis van gemeenschappelijke veldwaarden. Verschillende soorten samenvoegingen kunnen verschillende resultaten opleveren, afhankelijk van hoe niet-overeenkomende rijen moeten worden verwerkt. In deze handleiding bespreken we de verschillende soorten joins die PostgreSQL biedt en hoe u deze kunt gebruiken om tabelgegevens uit meerdere bronnen te combineren.



Wat zijn joins?

Kortom, wordt lid zijn een manier om gegevens uit meerdere tabellen weer te geven. Ze doen dit door records uit verschillende bronnen aan elkaar te koppelen op basis van overeenkomende waarden in bepaalde kolommen. Elke resulterende rij bestaat uit een record uit de eerste tabel gecombineerd met een rij uit de tweede tabel, gebaseerd op een of meer kolommen in elke tabel met dezelfde waarde.

De basissyntaxis van een join ziet er als volgt uit:

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

In een join wordt elke resulterende rij geconstrueerd door alle kolommen van de eerste tabel op te nemen, gevolgd door alle kolommen uit de tweede tabel. De SELECT gedeelte van de zoekopdracht kan worden gebruikt om de exacte kolommen te specificeren die u wilt weergeven.

Er kunnen meerdere rijen worden samengesteld uit de originele tabellen als de waarden in de kolommen die voor vergelijking worden gebruikt niet uniek zijn. Stel u bijvoorbeeld voor dat u een kolom vergelijkt uit de eerste tabel die twee records heeft met de waarde "rood". Hiermee matcht een kolom uit de tweede tabel met drie rijen met die waarde. De samenvoeging zal zes verschillende rijen voor die waarde produceren die de verschillende combinaties vertegenwoordigen die kunnen worden bereikt.

Het type join en de join-voorwaarden bepalen hoe elke rij die wordt weergegeven, is opgebouwd. Dit heeft invloed op wat er gebeurt met de rijen van elke tabel die wel en niet niet . doen een match hebben op de deelnamevoorwaarde.

Gemakshalve matchen veel joins de primaire sleutel op de ene tabel met een bijbehorende externe sleutel op de tweede tabel. Hoewel primaire en externe sleutels alleen door het databasesysteem worden gebruikt om consistentiegaranties te behouden, maakt hun relatie ze vaak een goede kandidaat voor deelnamevoorwaarden.



Verschillende soorten joins

Er zijn verschillende soorten joins beschikbaar, die elk mogelijk verschillende resultaten opleveren. Als u begrijpt hoe elk type is opgebouwd, kunt u bepalen welk type geschikt is voor verschillende scenario's.


Inner join

De standaard join heet een inner join . In PostgreSQL kan dit worden gespecificeerd met INNER JOIN of gewoon JOIN .

Hier is een typisch voorbeeld dat de syntaxis van een inner join demonstreert:

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

Een inner join is het meest beperkende type join omdat het alleen rijen weergeeft die zijn gemaakt door rijen uit elke tabel te combineren. Alle rijen in de samenstellende tabellen die geen overeenkomende tegenhanger in de andere tabel hadden, worden uit de resultaten verwijderd. Als de eerste tabel bijvoorbeeld de waarde 'blauw' heeft in de vergelijkingskolom en de tweede tabel geen record met die waarde heeft, wordt die rij onderdrukt in de uitvoer.

Als u de resultaten weergeeft als een Venn-diagram van de componententabellen, kunt u met een inner join het overlappende gebied van de twee cirkels weergeven. Geen van de waarden die alleen in een van de tabellen bestonden, wordt weergegeven.



Linker join

Een left join is een join die alle records toont die in een inner join zijn gevonden, plus alle niet-overeenkomende rijen van de eerste tabel. In PostgreSQL kan dit worden gespecificeerd als een LEFT OUTER JOIN of gewoon een LEFT JOIN .

De basissyntaxis van een left join volgt dit patroon:

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

Een left join wordt gemaakt door eerst een inner join uit te voeren om rijen te construeren uit alle overeenkomende records in beide tabellen. Daarna worden ook de ongeëvenaarde records uit de eerste tabel meegenomen. Aangezien elke rij in een join de kolommen van beide tabellen bevat, gebruiken de niet-overeenkomende kolommen NULL als de waarde voor alle kolommen in de tweede tabel.

Als u de resultaten weergeeft als een Venn-diagram van de componententabellen, kunt u met een left join de hele linkercirkel voorstellen. De delen van de linker cirkel die worden vertegenwoordigd door het snijpunt tussen de twee cirkels zullen aanvullende gegevens bevatten, aangevuld met de rechter tabel.



Right join

Een juiste join is een join die alle records toont die in een inner join zijn gevonden, plus alle niet-overeenkomende rijen uit de tweede tabel. In PostgreSQL kan dit worden gespecificeerd als een RIGHT OUTER JOIN of gewoon een RIGHT JOIN .

De basissyntaxis van een right join volgt dit patroon:

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

Een rechter join wordt gemaakt door eerst een inner join uit te voeren om rijen te construeren uit alle overeenkomende records in beide tabellen. Daarna worden ook de ongeëvenaarde records uit de tweede tabel meegenomen. Aangezien elke rij in een join de kolommen van beide tabellen bevat, gebruiken de niet-overeenkomende kolommen NULL als de waarde voor alle kolommen in de eerste tabel.

Als u de resultaten weergeeft als een Venn-diagram van de componententabellen, kunt u met een right join de hele rechtercirkel weergeven. De delen van de rechtercirkel die worden vertegenwoordigd door het snijpunt tussen de twee cirkels zullen aanvullende gegevens bevatten, aangevuld met de linkertabel.



Volledige deelname

Een volledige join is een join die alle records toont die in een inner join zijn gevonden, plus alle niet-overeenkomende rijen uit beide componenttabellen. In PostgreSQL kan dit worden gespecificeerd als een FULL OUTER JOIN of gewoon een FULL JOIN .

De basissyntaxis van een volledige join volgt dit patroon:

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

Een volledige join wordt gemaakt door eerst een inner join uit te voeren om rijen te construeren uit alle overeenkomende records in beide tabellen. Daarna worden ook de ongeëvenaarde records uit beide tabellen meegenomen. Aangezien elke rij in een join de kolommen van beide tabellen bevat, gebruiken de niet-overeenkomende kolommen NULL als de waarde voor alle kolommen in de ongeëvenaarde andere tabel.

Als u de resultaten weergeeft als een Venn-diagram van de componenttabellen, stelt een volledige join u in staat om beide componentcirkels volledig weer te geven. Het snijpunt van de twee cirkels heeft waarden die worden geleverd door elk van de samenstellende tabellen. De delen van de cirkels buiten het overlappende gebied hebben de waarden uit de tabel waar ze bij horen, met behulp van NULL om de kolommen in de andere tabel in te vullen.



Cross-join

Een speciale join genaamd een CROSS JOIN is ook beschikbaar. Een cross join gebruikt geen vergelijkingen om te bepalen of de rijen in elke tabel met elkaar overeenkomen. In plaats daarvan worden de resultaten samengesteld door eenvoudigweg elk van de rijen van de eerste tabel toe te voegen aan elk van de rijen van de tweede tabel.

Dit levert een Cartesiaans product op van de rijen in twee of meer tabellen. In feite combineert deze stijl van samenvoegen rijen uit elke tabel onvoorwaardelijk. Dus als elke tabel drie rijen heeft, zou de resulterende tabel negen rijen hebben die alle kolommen van beide tabellen bevatten.

Als u bijvoorbeeld een tabel heeft met de naam t1 gecombineerd met een tabel genaamd t2 , elk met rijen r1 , r2 , en r3 , het resultaat zou negen rijen zijn, als volgt gecombineerd:

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


Self join

Een self-join is elke join die de rijen van een tabel met zichzelf combineert. Het is misschien niet meteen duidelijk hoe dit nuttig kan zijn, maar het heeft eigenlijk veel algemene toepassingen.

Tabellen beschrijven vaak entiteiten die in relatie tot elkaar meerdere rollen kunnen vervullen. Als u bijvoorbeeld een tabel heeft met people , elke rij kan mogelijk een mother bevatten kolom die verwijst naar andere people in de tafel. Met een self-join kunt u deze verschillende rijen samenvoegen door een tweede exemplaar van de tabel samen te voegen met de eerste waar deze waarden overeenkomen.

Aangezien self-joins twee keer naar dezelfde tabel verwijzen, zijn tabelaliassen vereist om de verwijzingen ondubbelzinnig te maken. In het bovenstaande voorbeeld zou je bijvoorbeeld de twee instanties van de people . kunnen samenvoegen tabel met de aliassen people AS children en people AS mothers . Op die manier kunt u specificeren naar welke instantie van de tabel u verwijst bij het definiëren van join-voorwaarden.

Hier is nog een voorbeeld, dit keer voor relaties tussen werknemers en managers:

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



Deelnamevoorwaarden

Bij het combineren van tabellen bepaalt de join-voorwaarde hoe rijen aan elkaar worden gekoppeld om de samengestelde resultaten te vormen. Het uitgangspunt is om de kolommen in elke tabel te definiëren die moeten overeenkomen om de join op die rij te laten plaatsvinden.


De ON clausule

De meest standaard manier om de voorwaarden voor tabeljoins te definiëren is met de ON clausule. De ON clausule gebruikt een isgelijkteken om de exacte kolommen van elke tabel op te geven die worden vergeleken om te bepalen wanneer een join kan plaatsvinden. PostgreSQL gebruikt de geleverde kolommen om de rijen van elke tabel aan elkaar te naaien.

De ON clausule is de meest uitgebreide, maar ook de meest flexibele van de beschikbare toetredingsvoorwaarden. Het zorgt voor specificiteit, ongeacht hoe gestandaardiseerd de kolomnamen zijn van elke tabel die wordt gecombineerd.

De basissyntaxis van de ON clausule ziet er als volgt uit:

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

Hier, de rijen van table1 en table2 zal worden toegevoegd wanneer de id kolom uit table1 komt overeen met de ident kolom uit table2 . Omdat er een inner join wordt gebruikt, tonen de resultaten alleen de rijen die zijn samengevoegd. Aangezien de zoekopdracht het jokerteken * . gebruikt teken, worden alle kolommen van beide tabellen weergegeven.

Dit betekent dat zowel de id kolom uit table1 en de ident kolom uit table2 worden weergegeven, ook al hebben ze exact dezelfde waarde omdat ze aan de join-voorwaarde voldoen. U kunt deze duplicatie voorkomen door de exacte kolommen op te roepen die u wilt weergeven in de SELECT kolommenlijst.



De USING clausule

De USING clausule is een afkorting voor het specificeren van de voorwaarden van een ON clausule die kan worden gebruikt wanneer de kolommen die worden vergeleken dezelfde naam hebben in beide tabellen. De USING clausule neemt een lijst, tussen haakjes, van de gedeelde kolomnamen die moeten worden vergeleken.

De algemene syntaxis van de USING clausule gebruikt dit formaat:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Deze join combineert table1 met table2 wanneer twee kolommen die beide tabellen delen (id en state ) hebben elk overeenkomende waarden.

Deze zelfde join kan uitgebreider worden uitgedrukt met ON zoals dit:

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

Hoewel beide bovenstaande joins ertoe zouden leiden dat dezelfde rijen worden geconstrueerd met dezelfde aanwezige gegevens, zouden ze iets anders worden weergegeven. Terwijl de ON clausule bevat alle kolommen van beide tabellen, de USING clausule onderdrukt de dubbele kolommen. Dus in plaats van twee aparte id kolommen en twee aparte state kolommen (één voor elke tabel), zouden de resultaten slechts één van elk van de gedeelde kolommen hebben, gevolgd door alle andere kolommen die worden geleverd door table1 en table2 .



De NATURAL clausule

De NATURAL clausule is nog een andere afkorting die de breedsprakigheid van de USING . verder kan verminderen clausule. Een NATURAL join specificeert geen kolommen te matchen. In plaats daarvan voegt PostgreSQL automatisch de tabellen samen op basis van alle kolommen die overeenkomende kolommen in elke database hebben.

De algemene syntaxis van de NATURAL join-clausule ziet er als volgt uit:

SELECT    *FROM    table1NATURAL JOIN    table2;

Ervan uitgaande dat table1 en table2 beide hebben kolommen met de naam id , state , en company , zou de bovenstaande zoekopdracht gelijk zijn aan deze zoekopdracht met de ON clausule:

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

En deze zoekopdracht met de USING clausule:

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

Zoals de USING clausule, de NATURAL clausule onderdrukt dubbele kolommen, zodat er slechts één exemplaar van elk van de samengevoegde kolommen in de resultaten zou zijn.

Terwijl de NATURAL clausule de breedsprakigheid van uw vragen kan verminderen, moet u voorzichtig zijn bij het gebruik ervan. Omdat de kolommen die worden gebruikt om de tabellen samen te voegen automatisch worden berekend, kunnen de resultaten enorm verschillen als de kolommen in de componenttabellen veranderen als gevolg van nieuwe join-voorwaarden.




Deelnamevoorwaarden en de WHERE clausule

Deelnamevoorwaarden hebben veel kenmerken gemeen met de vergelijkingen die worden gebruikt om rijen gegevens te filteren met behulp van WHERE clausules. Beide constructies definiëren expressies die moeten worden geëvalueerd als waar om de rij te overwegen. Hierdoor is het niet altijd intuïtief wat het verschil is tussen het opnemen van extra vergelijkingen in een WHERE construeren versus ze definiëren binnen de join-clausule zelf.

Om de verschillen te begrijpen die zullen resulteren, moeten we kijken naar de volgorde waarin PostgreSQL verschillende delen van een query verwerkt. In dit geval worden de predikaten in de join-voorwaarde eerst verwerkt om de virtuele samengevoegde tabel in het geheugen te construeren. Na deze fase worden de uitdrukkingen binnen de WHERE clausule worden geëvalueerd om de resulterende rijen te filteren.

Stel bijvoorbeeld dat we twee tabellen hebben met de naam customer en order die we moeten samenvoegen. We willen de twee tabellen samenvoegen door de customer.id kolom met de order.customer_id kolom. Daarnaast zijn we geïnteresseerd in de rijen in de order tabel met een product_id van 12345.

Gezien de bovenstaande vereisten, hebben we twee voorwaarden waar we om geven. De manier waarop we deze voorwaarden uitdrukken, bepaalt echter de resultaten die we ontvangen.

Laten we eerst beide gebruiken als deelnamevoorwaarden voor een 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;

De resultaten kunnen er mogelijk ongeveer zo uitzien:

 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 kwam tot dit resultaat door de volgende bewerkingen uit te voeren:

  1. Combineer alle rijen in de customer tabel met de order tabel waar:
    • customer.id komt overeen met order.customer_id .
    • order.product_id komt overeen met 12345
  2. Omdat we een left-join gebruiken, moet u alle niet-overeenkomende . opnemen rijen uit de linkertabel (customer ), vul de kolommen uit de rechtertabel uit (order ) met NULL waarden.
  3. Alleen de kolommen weergeven die worden vermeld in de SELECT kolomspecificatie.

Het resultaat is dat al onze samengevoegde rijen voldoen aan beide voorwaarden waarnaar we op zoek zijn. De linker join zorgt er echter voor dat PostgreSQL ook alle rijen uit de eerste tabel opneemt die niet aan de join-voorwaarde voldeden. Dit resulteert in "overgebleven" rijen die de schijnbare bedoeling van de zoekopdracht niet lijken te volgen.

Als we de tweede zoekopdracht (order.product_id =12345) naar een WHERE clausule, in plaats van het op te nemen als een join-voorwaarde, krijgen we verschillende resultaten:

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;

Deze keer worden er slechts drie rijen weergegeven:

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

De volgorde waarin de vergelijkingen worden uitgevoerd, is de reden voor deze verschillen. Deze keer verwerkt PostgreSQL de query als volgt:

  1. Combineer alle rijen in de customer tabel met de order tabel waar customer.id komt overeen met order.customer_id .
  2. Omdat we een left-join gebruiken, moet u alle niet-overeenkomende . opnemen rijen uit de linkertabel (customer ), vul de kolommen uit de rechtertabel uit (order ) met NULL waarden.
  3. Evalueer de WHERE clausule om alle rijen te verwijderen die geen 12345 hebben als de waarde voor de order.product_id kolom.
  4. Alleen de kolommen weergeven die worden vermeld in de SELECT kolomspecificatie.

Deze keer, ook al gebruiken we een left join, de WHERE clausule kapt de resultaten af ​​door alle rijen weg te filteren zonder de juiste product_id . Omdat niet-overeenkomende rijen product_id . zouden hebben ingesteld op NULL , worden hiermee alle niet-overeenkomende rijen verwijderd die zijn ingevuld door de linker join. Het verwijdert ook alle rijen die overeenkomen met de deelnamevoorwaarde die deze tweede controleronde niet hebben doorstaan.

Als u het basisproces begrijpt dat PostgreSQL gebruikt om uw query's uit te voeren, kunt u enkele gemakkelijk te maken maar moeilijk te debuggen fouten voorkomen terwijl u met uw gegevens werkt.



Conclusie

In deze handleiding hebben we besproken hoe met joins relationele databases gegevens uit verschillende tabellen kunnen combineren om waardevollere antwoorden te bieden. We hebben gesproken over de verschillende joins die PostgreSQL ondersteunt, de manier waarop elk type zijn resultaten verzamelt en wat u kunt verwachten bij het gebruik van specifieke soorten joins. Daarna hebben we verschillende manieren besproken om join-voorwaarden te definiëren en hebben we gekeken naar het samenspel tussen joins en de WHERE clausule kan tot verrassingen leiden.

Joins zijn een essentieel onderdeel van wat relationele databases krachtig en flexibel genoeg maakt om zoveel verschillende soorten query's te verwerken. Door gegevens te ordenen met gebruikmaking van logische grenzen en toch in staat te zijn de gegevens per geval op nieuwe manieren te recombineren, krijgen relationele databases zoals PostgreSQL een ongelooflijke veelzijdigheid. Door te leren hoe u deze samenvoeging tussen tabellen kunt uitvoeren, kunt u complexere zoekopdrachten maken en vertrouwen op de database om volledige afbeeldingen van uw gegevens te maken.




  1. De datumnotaties vinden die worden gebruikt voor een specifieke taal in SQL Server (T-SQL)

  2. Een tabelnaam als variabele

  3. Hoe SIGN() werkt in MariaDB

  4. Ontvang de eerste dag van de week in SQL Server