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

Utilizzo di join per combinare dati da tabelle diverse in PostgreSQL


Introduzione

La suddivisione dei dati correlati in tabelle separate può essere vantaggiosa dal punto di vista della coerenza, della flessibilità e di alcuni tipi di prestazioni. Tuttavia, è comunque necessario un modo ragionevole per reintegrare i record quando le informazioni pertinenti si estendono su più tabelle.

Nei database relazionali, join offrono un modo per combinare i record in due o più tabelle in base a valori di campo comuni. Diversi tipi di join possono ottenere risultati diversi a seconda di come devono essere gestite le righe non corrispondenti. In questa guida, discuteremo i vari tipi di join offerti da PostgreSQL e come puoi usarli per combinare i dati delle tabelle da più origini.



Cosa sono i join?

In breve, si unisce sono un modo per visualizzare i dati da più tabelle. Lo fanno unendo insieme record provenienti da fonti diverse in base ai valori corrispondenti in determinate colonne. Ciascuna riga risultante è costituita da un record della prima tabella combinato con una riga della seconda tabella, in base a una o più colonne di ciascuna tabella aventi lo stesso valore.

La sintassi di base di un join è simile alla seguente:

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

In un join, ogni riga risultante viene costruita includendo tutte le colonne della prima tabella seguite da tutte le colonne della seconda tabella. Il SELECT parte della query può essere utilizzata per specificare le colonne esatte che desideri visualizzare.

È possibile creare più righe dalle tabelle originali se i valori nelle colonne utilizzate per il confronto non sono univoci. Ad esempio, immagina di avere una colonna da confrontare dalla prima tabella che ha due record con un valore di "rosso". Abbinata a questa è una colonna della seconda tabella che ha tre righe con quel valore. Il join produrrà sei righe diverse per quel valore che rappresentano le varie combinazioni che possono essere ottenute.

Il tipo di join e le condizioni di join determinano la modalità di costruzione di ciascuna riga visualizzata. Ciò influisce su ciò che accade alle righe di ogni tabella che fanno e non avere una corrispondenza nella condizione di unione.

Per comodità, molti join corrispondono alla chiave primaria su una tabella con una chiave esterna associata sulla seconda tabella. Sebbene le chiavi primarie ed esterne siano utilizzate dal sistema di database solo per mantenere le garanzie di coerenza, la loro relazione spesso le rende un buon candidato per le condizioni di unione.



Diversi tipi di join

Sono disponibili vari tipi di join, ognuno dei quali produrrà potenzialmente risultati diversi. Capire come è costruito ogni tipo ti aiuterà a determinare quale è appropriato per diversi scenari.


Inner join

Il join predefinito è chiamato inner join . In PostgreSQL, questo può essere specificato usando INNER JOIN o semplicemente JOIN .

Ecco un tipico esempio che dimostra la sintassi di un inner join:

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

Un inner join è il tipo di join più restrittivo perché visualizza solo le righe create combinando le righe di ciascuna tabella. Tutte le righe nelle tabelle costituenti che non avevano una controparte corrispondente nell'altra tabella vengono rimosse dai risultati. Ad esempio, se la prima tabella ha un valore "blu" nella colonna di confronto e la seconda tabella non ha record con quel valore, quella riga verrà eliminata dall'output.

Se rappresenti i risultati come diagramma di Venn delle tabelle dei componenti, un inner join ti consente di rappresentare l'area di sovrapposizione dei due cerchi. Non viene visualizzato nessuno dei valori che esistevano solo in una delle tabelle.



Unisci a sinistra

Un left join è un join che mostra tutti i record trovati in un inner join, più tutti i non corrispondenti righe della prima tabella. In PostgreSQL, questo può essere specificato come LEFT OUTER JOIN o semplicemente come LEFT JOIN .

La sintassi di base di un join sinistro segue questo schema:

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

Un left join viene costruito eseguendo prima un inner join per costruire righe da tutti i record corrispondenti in entrambe le tabelle. Successivamente, vengono inclusi anche i record non corrispondenti della prima tabella. Poiché ogni riga in un join include le colonne di entrambe le tabelle, le colonne non corrispondenti utilizzano NULL come valore per tutte le colonne della seconda tabella.

Se rappresenti i risultati come diagramma di Venn delle tabelle dei componenti, un join sinistro ti consente di rappresentare l'intero cerchio sinistro. Le parti del cerchio sinistro rappresentate dall'intersezione tra i due cerchi avranno dati aggiuntivi integrati dalla tabella di destra.



Unisciti a destra

Un join destro è un join che mostra tutti i record trovati in un inner join, più tutti i non corrispondenti righe della seconda tabella. In PostgreSQL, questo può essere specificato come RIGHT OUTER JOIN o semplicemente come RIGHT JOIN .

La sintassi di base di un join destro segue questo schema:

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

Un join destro viene costruito eseguendo prima un inner join per costruire righe da tutti i record corrispondenti in entrambe le tabelle. Successivamente, vengono inclusi anche i record non corrispondenti della seconda tabella. Poiché ogni riga in un join include le colonne di entrambe le tabelle, le colonne non corrispondenti utilizzano NULL come valore per tutte le colonne della prima tabella.

Se rappresenti i risultati come un diagramma di Venn delle tabelle dei componenti, un join destro ti consente di rappresentare l'intero cerchio destro. Le parti del cerchio di destra rappresentate dall'intersezione tra i due cerchi avranno dati aggiuntivi integrati dalla tabella di sinistra.



Partecipazione completa

Un full join è un join che mostra tutti i record trovati in un inner join, più tutti i non corrispondenti righe da entrambe le tabelle dei componenti. In PostgreSQL, questo può essere specificato come FULL OUTER JOIN o semplicemente come FULL JOIN .

La sintassi di base di un join completo segue questo schema:

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

Un full join viene costruito eseguendo prima un inner join per costruire righe da tutti i record corrispondenti in entrambe le tabelle. Successivamente, vengono inclusi anche i record non corrispondenti di entrambe le tabelle. Poiché ogni riga in un join include le colonne di entrambe le tabelle, le colonne non corrispondenti utilizzano NULL come valore per tutte le colonne nell'altra tabella senza corrispondenza.

Se rappresenti i risultati come diagramma di Venn delle tabelle dei componenti, un full join ti consente di rappresentare interamente entrambi i cerchi dei componenti. L'intersezione dei due cerchi avrà valori forniti da ciascuna delle tabelle componenti. Le parti dei cerchi al di fuori dell'area di sovrapposizione avranno i valori della tabella a cui appartengono, utilizzando NULL per compilare le colonne che si trovano nell'altra tabella.



Cross join

Un join speciale chiamato CROSS JOIN è anche disponibile. Un cross join non utilizza alcun confronto per determinare se le righe in ogni tabella corrispondono. Invece, i risultati vengono costruiti semplicemente aggiungendo ciascuna delle righe della prima tabella a ciascuna delle righe della seconda tabella.

Questo produce un prodotto cartesiano delle righe in due o più tabelle. In effetti, questo stile di join combina le righe di ogni tabella incondizionatamente. Quindi, se ogni tabella ha tre righe, la tabella risultante avrà nove righe contenenti tutte le colonne di entrambe le tabelle.

Ad esempio, se hai una tabella chiamata t1 combinato con una tabella chiamata t2 , ciascuno con righe r1 , r2 e r3 , il risultato sarebbe nove righe combinate in questo modo:

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


Partecipazione automatica

Un self join è qualsiasi join che combina le righe di una tabella con se stesso. Potrebbe non essere immediatamente chiaro come questo possa essere utile, ma in realtà ha molte applicazioni comuni.

Spesso le tabelle descrivono entità che possono svolgere più ruoli in relazione tra loro. Ad esempio, se hai una tabella di people , ogni riga potrebbe potenzialmente contenere una mother colonna che fa riferimento ad altre people sul tavolo. Un'unione automatica ti consentirebbe di unire queste diverse righe unendo una seconda istanza della tabella alla prima in cui questi valori corrispondono.

Poiché i join automatici fanno riferimento due volte alla stessa tabella, sono necessari alias di tabella per disambiguare i riferimenti. Nell'esempio sopra, ad esempio, potresti unire le due istanze di people tabella usando gli alias people AS children e people AS mothers . In questo modo, puoi specificare a quale istanza della tabella ti riferisci quando definisci le condizioni di unione.

Ecco un altro esempio, questa volta che rappresenta le relazioni tra dipendenti e manager:

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



Condizioni di unione

Quando si combinano le tabelle, la condizione di unione determina in che modo le righe verranno abbinate insieme per formare i risultati compositi. La premessa di base è definire le colonne in ogni tabella che devono corrispondere affinché il join avvenga su quella riga.


Il ON clausola

Il modo più standard per definire le condizioni per i join di tabelle è con ON clausola. Il ON La clausola utilizza un segno di uguale per specificare le colonne esatte di ciascuna tabella che verranno confrontate per determinare quando potrebbe verificarsi un join. PostgreSQL utilizza le colonne fornite per unire le righe di ciascuna tabella.

Il ON La clausola è la più dettagliata, ma anche la più flessibile delle condizioni di join disponibili. Consente la specificità indipendentemente dalla standardizzazione dei nomi delle colonne di ciascuna tabella combinata.

La sintassi di base di ON la clausola si presenta così:

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

Qui, le righe da table1 e table2 sarà unito ogni volta che il id colonna da table1 corrisponde a ident colonna da table2 . Poiché viene utilizzato un inner join, i risultati mostreranno solo le righe che sono state unite. Poiché la query utilizza il carattere jolly * carattere, verranno visualizzate tutte le colonne di entrambe le tabelle.

Ciò significa che entrambi gli id colonna da table1 e l'ident colonna da table2 verranno visualizzati, anche se hanno lo stesso valore esatto in virtù del soddisfacimento della condizione di unione. Puoi evitare questa duplicazione richiamando le colonne esatte che desideri visualizzare nel SELECT elenco di colonne.



Il USING clausola

Il USING clausola è una scorciatoia per specificare le condizioni di un ON clausola che può essere utilizzata quando le colonne da confrontare hanno lo stesso nome in entrambe le tabelle. Il USING La clausola accetta un elenco, racchiuso tra parentesi, dei nomi delle colonne condivise che devono essere confrontati.

La sintassi generale di USING clausola utilizza questo formato:

SELECT    *FROM    table1JOIN    table2USING    (id, state);

Questo join combina table1 con table2 quando due colonne condivise da entrambe le tabelle (id e state ) ognuno ha valori corrispondenti.

Questo stesso join potrebbe essere espresso in modo più dettagliato usando ON così:

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

Sebbene entrambi i join precedenti comporteranno la costruzione delle stesse righe con gli stessi dati presenti, verrebbero visualizzati in modo leggermente diverso. Mentre il ON La clausola include tutte le colonne di entrambe le tabelle, USING La clausola elimina le colonne duplicate. Quindi, invece di esserci due id separati colonne e due state separati colonne (una per ogni tabella), i risultati avrebbero solo una di ciascuna delle colonne condivise, seguita da tutte le altre colonne fornite da table1 e table2 .



Il NATURAL clausola

Il NATURAL clausola è ancora un'altra scorciatoia che può ridurre ulteriormente la verbosità di USING clausola. Un NATURAL join non specifica nessuno colonne da abbinare. Invece, PostgreSQL unirà automaticamente le tabelle in base a tutte le colonne che hanno colonne corrispondenti in ogni database.

La sintassi generale del NATURAL la clausola di unione è simile a questa:

SELECT    *FROM    table1NATURAL JOIN    table2;

Supponendo che table1 e table2 entrambi hanno colonne denominate id , state e company , la query precedente sarebbe equivalente a questa query utilizzando ON clausola:

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

E questa query usando USING clausola:

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

Come il USING clausola, il NATURAL La clausola sopprime le colonne duplicate, quindi ci sarebbe solo una singola istanza di ciascuna delle colonne unite nei risultati.

Mentre il NATURAL la clausola può ridurre la verbosità delle tue domande, è necessario prestare attenzione quando la si utilizza. Poiché le colonne utilizzate per l'unione delle tabelle vengono calcolate automaticamente, se le colonne nelle tabelle dei componenti cambiano, i risultati possono essere molto diversi a causa delle nuove condizioni di unione.




Condizioni di unione e WHERE clausola

Le condizioni di unione condividono molte caratteristiche con i confronti utilizzati per filtrare le righe di dati utilizzando WHERE clausole. Entrambi i costrutti definiscono espressioni che devono restituire true affinché la riga venga considerata. Per questo motivo, non è sempre intuitivo quale sia la differenza tra l'inclusione di confronti aggiuntivi in ​​un WHERE costruire invece di definirli all'interno della clausola join stessa.

Per comprendere le differenze che ne risulteranno, dobbiamo dare un'occhiata all'ordine in cui PostgreSQL elabora le diverse porzioni di una query. In questo caso, i predicati nella condizione di join vengono elaborati per primi per costruire la tabella unita virtuale in memoria. Dopo questa fase, le espressioni all'interno di WHERE vengono valutate per filtrare le righe risultanti.

Ad esempio, supponiamo di avere due tabelle chiamate customer e order che dobbiamo unirci. Vogliamo unire le due tabelle facendo corrispondere il customer.id colonna con order.customer_id colonna. Inoltre, siamo interessati alle righe nell'order tabella che ha un product_id di 12345.

Dati i requisiti di cui sopra, abbiamo due condizioni a cui teniamo. Il modo in cui esprimiamo queste condizioni, tuttavia, determinerà i risultati che riceveremo.

Per prima cosa, usiamo entrambi come condizioni di unione per un 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;

I risultati potrebbero potenzialmente assomigliare a questo:

 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 è arrivato a questo risultato eseguendo le seguenti operazioni:

  1. Combina qualsiasi riga nel customer tabella con l'order tabella dove:
    • customer.id corrisponde a order.customer_id .
    • order.product_id corrisponde a 12345
  2. Poiché stiamo utilizzando un join sinistro, includi qualsiasi non corrispondente righe dalla tabella di sinistra (customer ), riempiendo le colonne della tabella di destra (order ) con NULL valori.
  3. Visualizza solo le colonne elencate in SELECT specifica della colonna.

Il risultato è che tutte le nostre righe unite soddisfano entrambe le condizioni che stiamo cercando. Tuttavia, il join sinistro fa sì che PostgreSQL includa anche tutte le righe della prima tabella che non soddisfano la condizione di join. Ciò si traduce in righe "rimaste" che non sembrano seguire l'intento apparente della query.

Se spostiamo la seconda query (order.product_id =12345) a un WHERE clausola, invece di includerla come condizione di join, otteniamo risultati diversi:

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;

Questa volta vengono visualizzate solo tre righe:

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

L'ordine in cui vengono eseguiti i confronti è la ragione di queste differenze. Questa volta, PostgreSQL elabora la query in questo modo:

  1. Combina qualsiasi riga nel customer tabella con l'order tabella dove customer.id corrisponde a order.customer_id .
  2. Poiché stiamo utilizzando un join sinistro, includi qualsiasi non corrispondente righe dalla tabella di sinistra (customer ), riempiendo le colonne della tabella di destra (order ) con NULL valori.
  3. Valuta il WHERE clausola per rimuovere tutte le righe che non hanno 12345 come valore per order.product_id colonna.
  4. Visualizza solo le colonne elencate in SELECT specifica della colonna.

Questa volta, anche se stiamo usando un join sinistro, il WHERE La clausola tronca i risultati filtrando tutte le righe senza il corretto product_id . Perché tutte le righe non corrispondenti avrebbero product_id impostato su NULL , questo rimuove tutte le righe non corrispondenti che sono state popolate dal join sinistro. Rimuove anche tutte le righe che sono state soddisfatte dalla condizione di unione che non hanno superato questo secondo round di controlli.

Comprendere il processo di base utilizzato da PostgreSQL per eseguire le query può aiutarti a evitare alcuni errori facili da commettere ma difficili da eseguire il debug mentre lavori con i tuoi dati.



Conclusione

In questa guida, abbiamo spiegato come i join consentono ai database relazionali di combinare i dati di tabelle diverse per fornire risposte più preziose. Abbiamo parlato dei vari join supportati da PostgreSQL, del modo in cui ogni tipo assembla i suoi risultati e di cosa aspettarsi quando si utilizzano tipi specifici di join. Successivamente, abbiamo esaminato diversi modi per definire le condizioni di unione e abbiamo esaminato l'interazione tra i join e il WHERE clausola può portare a sorprese.

I join sono una parte essenziale di ciò che rende i database relazionali sufficientemente potenti e flessibili da gestire così tanti tipi diversi di query. L'organizzazione dei dati utilizzando i confini logici, pur essendo in grado di ricombinare i dati in modi nuovi, caso per caso, offre ai database relazionali come PostgreSQL un'incredibile versatilità. Imparare come eseguire questa cucitura tra le tabelle ti consentirà di creare query più complesse e di fare affidamento sul database per creare immagini complete dei tuoi dati.