Risposte:
SQL JOIN
?SQL JOIN
è un metodo per recuperare i dati da due o più tabelle del database.
SQL JOIN
s?Ci sono un totale di cinque JOIN
secondi. Loro sono :
1. JOIN or INNER JOIN
2. OUTER JOIN
2.1 LEFT OUTER JOIN or LEFT JOIN
2.2 RIGHT OUTER JOIN or RIGHT JOIN
2.3 FULL OUTER JOIN or FULL JOIN
3. NATURAL JOIN
4. CROSS JOIN
5. SELF JOIN
In questo tipo di a JOIN
, otteniamo tutti i record che soddisfano la condizione in entrambe le tabelle e i record in entrambe le tabelle che non corrispondono non vengono riportati.
In altre parole, INNER JOIN
si basa sul singolo fatto che: SOLO le voci corrispondenti in ENTRAMBE le tabelle DOVREBBERO essere elencate.
Si noti che un JOIN
senza altre JOIN
parole chiave (come INNER
, OUTER
, LEFT
, ecc) è un INNER JOIN
. In altre parole, JOIN
è uno zucchero sintattico per INNER JOIN
(vedi: Differenza tra JOIN e INNER JOIN ).
OUTER JOIN
recupera
O, le righe corrispondenti da una tabella e tutte le righe nell'altra tabella Oppure, tutte le righe in tutte le tabelle (non importa se esiste o meno una corrispondenza).
Esistono tre tipi di Outer Join:
2.1 ISCRIVITI A SINISTRA ESTERNO o SINISTRA
Questo join restituisce tutte le righe della tabella di sinistra insieme alle righe corrispondenti della tabella di destra. Se non ci sono colonne corrispondenti nella tabella giusta, restituisce NULL
valori.
2.2 UNISCI ESTERNO DESTRA o UNISC. DESTRA
Ciò JOIN
restituisce tutte le righe dalla tabella di destra insieme alle righe corrispondenti dalla tabella di sinistra. Se non ci sono colonne corrispondenti nella tabella di sinistra, restituisce NULL
valori.
2.3 FULL OUTER JOIN o FULL JOIN
Questo JOIN
combina LEFT OUTER JOIN
e RIGHT OUTER JOIN
. Restituisce righe da entrambe le tabelle quando sono soddisfatte le condizioni e restituisce NULL
valore quando non vi è corrispondenza.
In altre parole, OUTER JOIN
si basa sul fatto che: DEVONO essere elencate SOLO le voci corrispondenti in UNA DELLE tabelle (DESTRA o SINISTRA) o ENTRAMBE delle tabelle (COMPLETA).
Note that `OUTER JOIN` is a loosened form of `INNER JOIN`.
Si basa sulle due condizioni:
JOIN
avviene su tutte le colonne con lo stesso nome per la parità.Questo sembra essere di natura più teorica e di conseguenza (probabilmente) la maggior parte dei DBMS non si preoccupa nemmeno di supportarlo.
È il prodotto cartesiano delle due tabelle coinvolte. Il risultato di una CROSS JOIN
volontà non avrà senso nella maggior parte delle situazioni. Inoltre, non avremo assolutamente bisogno di questo (o almeno necessario, per essere precisi).
Non è una diversa forma di JOIN
, ma è una JOIN
( INNER
, OUTER
, ecc) di una tabella con se stessa.
A seconda dell'operatore utilizzato per una JOIN
clausola, ci possono essere due tipi di JOIN
s. Loro sono
Per qualunque JOIN
tipo ( INNER
, OUTER
ecc.), Se utilizziamo SOLO l'operatore di uguaglianza (=), allora diciamo che JOIN
è un EQUI JOIN
.
È uguale a EQUI JOIN
ma consente a tutti gli altri operatori come>, <,> = ecc.
Molti considerano entrambi
EQUI JOIN
e ThetaJOIN
simili aINNER
,OUTER
eccJOIN
. Ma credo fermamente che sia un errore e rende vaghe le idee. PerchéINNER JOIN
,OUTER JOIN
ecc. Sono tutti collegati alle tabelle e ai loro dati mentreEQUI JOIN
eTHETA JOIN
sono collegati solo agli operatori che usiamo nel primo.Ancora una volta, ci sono molti che considerano
NATURAL JOIN
una sorta di "peculiare"EQUI JOIN
. In effetti, è vero, a causa della prima condizione di cui ho parlatoNATURAL JOIN
. Tuttavia, non dobbiamo limitarlo semplicemente aNATURAL JOIN
solo.INNER JOIN
s,OUTER JOIN
s etc potrebbe essereEQUI JOIN
anche un .
Definizione:
I JOIN sono un modo per interrogare i dati combinati insieme da più tabelle contemporaneamente.
Per quanto riguarda RDBMS ci sono 5 tipi di join:
Equi-Join: combina record comuni da due tabelle in base alla condizione di uguaglianza. Tecnicamente, Join fatto usando uguaglianza-operatore (=) per confrontare i valori della chiave primaria di una tabella e i valori della chiave esterna di un'altra tabella, quindi il set di risultati include record comuni (corrispondenti) da entrambe le tabelle. Per l'implementazione vedere INNER-JOIN.
Natural-Join: è la versione migliorata di Equi-Join, in cui l'operazione SELECT omette la colonna duplicata. Per l'implementazione vedere INNER-JOIN
Non-Equi-Join: è il contrario di Equi-join in cui la condizione di join utilizza un operatore diverso da uguale (=) ad es.! =, <=,> =,>, <O TRA ecc. Per l'implementazione, vedere INNER-JOIN.
Auto-join: un comportamento personalizzato di join in cui una tabella si combina con se stessa; Ciò è in genere necessario per l'interrogazione di tabelle autoreferenziali (o entità di relazione unaria). Per l'implementazione vedere INNER-JOINs.
Prodotto cartesiano: incrocia tutti i record di entrambe le tabelle senza alcuna condizione. Tecnicamente, restituisce il set di risultati di una query senza la clausola WHERE.
In base alle preoccupazioni e ai progressi di SQL, esistono 3 tipi di join e tutti i join RDBMS possono essere raggiunti utilizzando questi tipi di join.
INNER-JOIN: unisce (o combina) righe corrispondenti da due tabelle. La corrispondenza viene eseguita in base a colonne comuni di tabelle e alla loro operazione di confronto. Se condizione basata sull'uguaglianza, allora: EQUI-JOIN eseguita, altrimenti Non-EQUI-Join.
OUTER-JOIN: unisce (o combina) righe corrispondenti da due tabelle e righe senza corrispondenza con valori NULL. Tuttavia, è possibile personalizzare la selezione di righe non corrispondenti, ad es. Selezionando la riga non corrispondente dalla prima tabella o dalla seconda tabella in base ai sottotipi: SINISTRA ESTERNO UNISCI e DESTRA ESTERNO UNISC.
2.1. LEFT Outer JOIN (aka, LEFT-JOIN): restituisce le righe corrispondenti da due tabelle e non corrispondenti alla sola tabella LEFT (ovvero, prima tabella).
2.2. RIGHT Outer JOIN (aka, RIGHT-JOIN): restituisce le righe corrispondenti da due tabelle e non corrispondenti solo dalla tabella DESTRA.
2.3. FULL OUTER JOIN (aka OUTER JOIN): restituisce corrispondenze e non corrispondenti da entrambe le tabelle.
CROSS-JOIN: Questo join non unisce / combina invece esegue prodotti cartesiani.
Nota: Self-JOIN può essere ottenuto da INNER-JOIN, OUTER-JOIN e CROSS-JOIN in base ai requisiti, ma la tabella deve unirsi a se stessa.
1.1: INNER-JOIN: implementazione Equi-join
SELECT *
FROM Table1 A
INNER JOIN Table2 B ON A.<Primary-Key> =B.<Foreign-Key>;
1.2: INNER-JOIN: implementazione Natural-JOIN
Select A.*, B.Col1, B.Col2 --But no B.ForeignKeyColumn in Select
FROM Table1 A
INNER JOIN Table2 B On A.Pk = B.Fk;
1.3: INNER-JOIN con implementazione NON Equi-join
Select *
FROM Table1 A INNER JOIN Table2 B On A.Pk <= B.Fk;
1.4: INNER-JOIN con SELF-JOIN
Select *
FROM Table1 A1 INNER JOIN Table1 A2 On A1.Pk = A2.Fk;
2.1: OUTER JOIN (full outer join)
Select *
FROM Table1 A FULL OUTER JOIN Table2 B On A.Pk = B.Fk;
2.2: ISCRIVITI A SINISTRA
Select *
FROM Table1 A LEFT OUTER JOIN Table2 B On A.Pk = B.Fk;
2.3: ISCRIVITI A DESTRA
Select *
FROM Table1 A RIGHT OUTER JOIN Table2 B On A.Pk = B.Fk;
3.1: CROSS JOIN
Select *
FROM TableA CROSS JOIN TableB;
3.2: CROSS JOIN-Self JOIN
Select *
FROM Table1 A1 CROSS JOIN Table1 A2;
//O//
Select *
FROM Table1 A1,Table1 A2;
intersect
/ except
/ union
; qui i cerchi sono le righe restituite da left
& right
join
, come dicono le etichette numerate. L'immagine AXB non ha senso. cross join
= inner join on 1=1
& è un caso speciale del primo diagramma.
UNION JOIN
. Ora reso obsoleto in SQL: 2003.
È interessante notare che la maggior parte delle altre risposte soffre di questi due problemi:
Di recente ho scritto un articolo sull'argomento: una guida probabilmente incompleta e completa ai molti modi diversi di unire le tabelle in SQL , che riassumerò qui.
Ecco perché i diagrammi di Venn li spiegano in modo così impreciso, perché un JOIN crea un prodotto cartesiano tra le due tabelle unite. Wikipedia lo illustra bene:
La sintassi SQL per i prodotti cartesiani è CROSS JOIN
. Per esempio:
SELECT *
-- This just generates all the days in January 2017
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Here, we're combining all days with all departments
CROSS JOIN departments
Che combina tutte le righe di una tabella con tutte le righe dell'altra tabella:
Fonte:
+--------+ +------------+
| day | | department |
+--------+ +------------+
| Jan 01 | | Dept 1 |
| Jan 02 | | Dept 2 |
| ... | | Dept 3 |
| Jan 30 | +------------+
| Jan 31 |
+--------+
Risultato:
+--------+------------+
| day | department |
+--------+------------+
| Jan 01 | Dept 1 |
| Jan 01 | Dept 2 |
| Jan 01 | Dept 3 |
| Jan 02 | Dept 1 |
| Jan 02 | Dept 2 |
| Jan 02 | Dept 3 |
| ... | ... |
| Jan 31 | Dept 1 |
| Jan 31 | Dept 2 |
| Jan 31 | Dept 3 |
+--------+------------+
Se scriviamo un elenco di tabelle separato da virgole, otterremo lo stesso:
-- CROSS JOINing two tables:
SELECT * FROM table1, table2
An INNER JOIN
è solo un filtro in CROSS JOIN
cui il predicato del filtro viene chiamato Theta
nell'algebra relazionale.
Per esempio:
SELECT *
-- Same as before
FROM generate_series(
'2017-01-01'::TIMESTAMP,
'2017-01-01'::TIMESTAMP + INTERVAL '1 month -1 day',
INTERVAL '1 day'
) AS days(day)
-- Now, exclude all days/departments combinations for
-- days before the department was created
JOIN departments AS d ON day >= d.created_at
Si noti che la parola chiave INNER
è facoltativa (tranne in MS Access).
( guarda l'articolo per esempi di risultati )
Un tipo speciale di Theta-JOIN è equi JOIN, che usiamo di più. Il predicato unisce la chiave primaria di una tabella con la chiave esterna di un'altra tabella. Se utilizziamo il database Sakila per l'illustrazione, possiamo scrivere:
SELECT *
FROM actor AS a
JOIN film_actor AS fa ON a.actor_id = fa.actor_id
JOIN film AS f ON f.film_id = fa.film_id
Questo combina tutti gli attori con i loro film.
O anche, su alcuni database:
SELECT *
FROM actor
JOIN film_actor USING (actor_id)
JOIN film USING (film_id)
La USING()
sintassi consente di specificare una colonna che deve essere presente su entrambi i lati delle tabelle di un'operazione JOIN e crea un predicato di uguaglianza su quelle due colonne.
Altre risposte hanno elencato questo "tipo JOIN" separatamente, ma non ha senso. È solo una forma di zucchero di sintassi per equi JOIN, che è un caso speciale di Theta-JOIN o INNER JOIN. NATURAL JOIN raccoglie semplicemente tutte le colonne comuni a entrambe le tabelle da unire e unisce USING()
quelle colonne. Che non è quasi mai utile, a causa di corrispondenze accidentali (come LAST_UPDATE
colonne nel database Sakila ).
Ecco la sintassi:
SELECT *
FROM actor
NATURAL JOIN film_actor
NATURAL JOIN film
Ora, OUTER JOIN
è un po 'diverso da INNER JOIN
come crea uno UNION
dei numerosi prodotti cartesiani. Possiamo scrivere:
-- Convenient syntax:
SELECT *
FROM a LEFT JOIN b ON <predicate>
-- Cumbersome, equivalent syntax:
SELECT a.*, b.*
FROM a JOIN b ON <predicate>
UNION ALL
SELECT a.*, NULL, NULL, ..., NULL
FROM a
WHERE NOT EXISTS (
SELECT * FROM b WHERE <predicate>
)
Nessuno vuole scrivere quest'ultimo, quindi scriviamo OUTER JOIN
(che di solito è meglio ottimizzato dai database).
Ad esempio INNER
, la parola chiave OUTER
è facoltativa, qui.
OUTER JOIN
è disponibile in tre gusti:
LEFT [ OUTER ] JOIN
: La tabella di sinistra JOIN
dell'espressione viene aggiunta all'unione come mostrato sopra.RIGHT [ OUTER ] JOIN
: La tabella giusta JOIN
dell'espressione viene aggiunta all'unione come mostrato sopra.FULL [ OUTER ] JOIN
: Entrambe le tabelle JOIN
dell'espressione vengono aggiunte all'unione come mostrato sopra.Tutti questi possono essere combinati con la parola chiave USING()
o con NATURAL
( ho effettivamente avuto un caso d'uso reale per un NATURAL FULL JOIN
recente )
Esistono alcune sintassi obsolete storiche in Oracle e SQL Server, supportate OUTER JOIN
già prima che lo standard SQL avesse una sintassi per questo:
-- Oracle
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id = fa.actor_id(+)
AND fa.film_id = f.film_id(+)
-- SQL Server
SELECT *
FROM actor a, film_actor fa, film f
WHERE a.actor_id *= fa.actor_id
AND fa.film_id *= f.film_id
Detto questo, non usare questa sintassi. Ho appena elencato questo qui in modo da poterlo riconoscere dai vecchi post di blog / codice legacy.
OUTER JOIN
Pochi lo sanno, ma lo standard SQL specifica partizionato OUTER JOIN
(e Oracle lo implementa). Puoi scrivere cose come questa:
WITH
-- Using CONNECT BY to generate all dates in January
days(day) AS (
SELECT DATE '2017-01-01' + LEVEL - 1
FROM dual
CONNECT BY LEVEL <= 31
),
-- Our departments
departments(department, created_at) AS (
SELECT 'Dept 1', DATE '2017-01-10' FROM dual UNION ALL
SELECT 'Dept 2', DATE '2017-01-11' FROM dual UNION ALL
SELECT 'Dept 3', DATE '2017-01-12' FROM dual UNION ALL
SELECT 'Dept 4', DATE '2017-04-01' FROM dual UNION ALL
SELECT 'Dept 5', DATE '2017-04-02' FROM dual
)
SELECT *
FROM days
LEFT JOIN departments
PARTITION BY (department) -- This is where the magic happens
ON day >= created_at
Parti del risultato:
+--------+------------+------------+
| day | department | created_at |
+--------+------------+------------+
| Jan 01 | Dept 1 | | -- Didn't match, but still get row
| Jan 02 | Dept 1 | | -- Didn't match, but still get row
| ... | Dept 1 | | -- Didn't match, but still get row
| Jan 09 | Dept 1 | | -- Didn't match, but still get row
| Jan 10 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 11 | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 12 | Dept 1 | Jan 10 | -- Matches, so get join result
| ... | Dept 1 | Jan 10 | -- Matches, so get join result
| Jan 31 | Dept 1 | Jan 10 | -- Matches, so get join result
Il punto qui è che tutte le righe dal lato partizionato del join finiranno nel risultato indipendentemente dal fatto che JOIN
qualcosa corrisponda sull'altro lato del JOIN. Per farla breve: serve per riempire i dati sparsi nei rapporti. Molto utile!
Sul serio? Nessun'altra risposta ha capito? Certo che no, perché non ha una sintassi nativa in SQL, sfortunatamente (proprio come ANTI JOIN di seguito). Ma possiamo usare IN()
e EXISTS()
, ad esempio, trovare tutti gli attori che hanno recitato nei film:
SELECT *
FROM actor a
WHERE EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Il WHERE a.actor_id = fa.actor_id
predicato funge da predicato semi join. Se non ci credi, controlla i piani di esecuzione, ad es. In Oracle. Vedrai che il database esegue un'operazione SEMI JOIN, non il EXISTS()
predicato.
Questo è esattamente l'opposto di SEMI JOIN ( fare attenzione a non usare NOT IN
però , in quanto ha un importante avvertimento)
Ecco tutti gli attori senza film:
SELECT *
FROM actor a
WHERE NOT EXISTS (
SELECT * FROM film_actor fa
WHERE a.actor_id = fa.actor_id
)
Alcune persone (specialmente le persone MySQL) scrivono anche ANTI JOIN in questo modo:
SELECT *
FROM actor a
LEFT JOIN film_actor fa
USING (actor_id)
WHERE film_id IS NULL
Penso che la ragione storica sia la prestazione.
OMG, questo è troppo bello. Sono l'unico a menzionarlo? Ecco una bella domanda:
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
LEFT OUTER JOIN LATERAL (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN inventory AS i USING (film_id)
JOIN rental AS r USING (inventory_id)
JOIN payment AS p USING (rental_id)
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
ON true
Troverà i primi 5 film che producono entrate per attore. Ogni volta che hai bisogno di una query TOP-N-per-qualcosa, LATERAL JOIN
sarà tuo amico. Se sei una persona di SQL Server, conosci questo JOIN
tipo sotto il nomeAPPLY
SELECT a.first_name, a.last_name, f.*
FROM actor AS a
OUTER APPLY (
SELECT f.title, SUM(amount) AS revenue
FROM film AS f
JOIN film_actor AS fa ON f.film_id = fa.film_id
JOIN inventory AS i ON f.film_id = i.film_id
JOIN rental AS r ON i.inventory_id = r.inventory_id
JOIN payment AS p ON r.rental_id = p.rental_id
WHERE fa.actor_id = a.actor_id -- JOIN predicate with the outer query!
GROUP BY f.film_id
ORDER BY revenue DESC
LIMIT 5
) AS f
OK, forse questo è barare, perché a LATERAL JOIN
o APPLY
expression è davvero una "sottoquery correlata" che produce più righe. Ma se consentiamo "sottoquery correlate", possiamo anche parlare di ...
Questo è veramente implementato solo da Oracle e Informix (per quanto ne sappia), ma può essere emulato in PostgreSQL usando array e / o XML e in SQL Server usando XML.
MULTISET
produce una sottoquery correlata e nidifica il set di righe risultante nella query esterna. La query seguente seleziona tutti gli attori e per ogni attore raccoglie i loro film in una raccolta nidificata:
SELECT a.*, MULTISET (
SELECT f.*
FROM film AS f
JOIN film_actor AS fa USING (film_id)
WHERE a.actor_id = fa.actor_id
) AS films
FROM actor
Come avete visto, ci sono più tipi di JOIN non solo il "noioso" INNER
, OUTER
e CROSS JOIN
che di solito sono menzionati. Maggiori dettagli nel mio articolo . E per favore, smetti di usare i diagrammi di Venn per illustrarli.
Ho intenzione di spingere il mio animale domestico: la parola chiave USING.
Se entrambe le tabelle su entrambi i lati del JOIN hanno le loro chiavi esterne correttamente denominate (cioè, lo stesso nome, non solo "id), allora questo può essere usato:
SELECT ...
FROM customers JOIN orders USING (customer_id)
Lo trovo molto pratico, leggibile e non usato abbastanza spesso.