Join interno, join esterno, join incrociato? Cosa dà?
È una domanda valida. Una volta ho visto un codice Visual Basic con codici T-SQL incorporati. Il codice VB recupera i record della tabella con più istruzioni SELECT, una SELECT * per tabella. Quindi, combina più set di risultati in un set di record. Assurdo?
Per i giovani sviluppatori che l'hanno fatto, non lo era. Ma quando mi hanno chiesto di valutare il motivo per cui il sistema era lento, quel problema è stato il primo ad attirare la mia attenzione. Giusto. Non hanno mai sentito parlare di join SQL. In tutta onestà, sono stati onesti e aperti ai suggerimenti.
Come descrivi i join SQL? Forse ti ricordi una canzone:Imagine di John Lennon:
Puoi dire che sono un sognatore, ma non sono l'unico.
Spero che un giorno ti unirai a noi e il mondo sarà come uno.
Nel contesto della canzone, unirsi è unire. In un database SQL, la combinazione di record di 2 o più tabelle in un set di risultati forma un join .
Questo articolo è l'inizio di una serie in 3 parti che parla di join SQL:
- UNIONE INTERNA
- OUTER JOIN, che include SINISTRA, DESTRA e COMPLETA
- CROSS UNISCITI
Ma prima di iniziare a discutere di INNER JOIN, descriviamo i join in generale.
Ulteriori informazioni su SQL JOIN
I join vengono visualizzati subito dopo la clausola FROM. Nella sua forma più semplice, sembra usare lo standard SQL-92:
FROM <table source> [<alias1>]
<join type> JOIN <table source> [<alias2>] [ON <join condition>]
[<join type> JOIN <table source> [<alias3>] [ON <join condition>]
<join type> JOIN <table source> [<aliasN>] [ON <join condition>]]
[WHERE <condition>]
Descriviamo le cose quotidiane che circondano il JOIN.
Fonti tabella
È possibile aggiungere fino a 256 origini tabelle, secondo Microsoft. Naturalmente, dipende dalle risorse del tuo server. Non ho mai aderito a più di 10 tavoli in vita mia, per non parlare di 256. Ad ogni modo, le fonti delle tabelle possono essere una delle seguenti:
- Tabella
- Visualizza
- Tabella o visualizza sinonimo
- Variabile tabella
- Funzione con valori di tabella
- Tabella derivata
Alias tabella
Un alias è facoltativo, ma accorcia il codice e riduce al minimo la digitazione. Consente inoltre di evitare errori quando esiste un nome di colonna in due o più tabelle utilizzate in SELECT, UPDATE, INSERT o DELETE. Aggiunge anche chiarezza al tuo codice. È facoltativo, ma consiglierei di utilizzare gli alias. (A meno che non ti piaccia digitare le origini delle tabelle per nome.)
Condizione di adesione
La parola chiave ON precede la condizione di join che può essere un join singolo o colonne a 2 chiavi delle 2 tabelle unite. Oppure può essere un join composito che utilizza più di 2 colonne chiave. Definisce come sono correlate le tabelle.
Tuttavia, utilizziamo la condizione di unione solo per i join INNER e OUTER. Il suo utilizzo su un CROSS JOIN attiverà un errore.
Poiché le condizioni di unione definiscono le relazioni, hanno bisogno di operatori.
Il più comune degli operatori di condizioni di join è l'operatore di uguaglianza (=). Anche altri operatori come> o
La maggior parte dei join può essere riscritta come subquery e viceversa. Consulta questo articolo per ulteriori informazioni sulle sottoquery rispetto ai join.
L'utilizzo di tabelle derivate in un join è simile al seguente:
Si unisce dal risultato di un'altra istruzione SELECT ed è perfettamente valido.
Avrai più esempi, ma affrontiamo un'ultima cosa su SQL JOINS. È il modo in cui Query Optimizer di SQL Server elabora i join.
Per capire come funziona il processo, devi conoscere i due tipi di operazioni coinvolte:
Una parola:prestazioni.
Una cosa è sapere come formare query con i join per produrre risultati corretti. Un altro è farlo funzionare il più velocemente possibile. Devi essere molto preoccupato per questo se vuoi una buona reputazione con i tuoi utenti.
Quindi, a cosa devi prestare attenzione nel Piano di esecuzione per queste operazioni logiche?
I suggerimenti per il join sono una novità in SQL Server 2019. Quando lo usi nei tuoi join, indica a Query Optimizer di interrompere la decisione di cosa è meglio per la query. Sei il capo quando si tratta del join fisico da utilizzare.
Ora fermati, proprio lì. La verità è che Query Optimizer in genere seleziona il miglior join fisico per la tua query. Se non sai cosa stai facendo, non utilizzare i suggerimenti di partecipazione.
I possibili suggerimenti che puoi specificare sono LOOP, MERGE, HASH o REMOTE.
Non ho usato i suggerimenti di partecipazione, ma ecco la sintassi:
INNER JOIN restituisce le righe con i record corrispondenti in entrambe le tabelle, in base a una condizione. È anche il join predefinito se non specifichi la parola chiave INNER:
Come puoi vedere, righe corrispondenti da Tabella1 e Tabella2 vengono restituiti utilizzando Key1 come condizione di unione. La Tabella1 record con Chiave1 ='C' è esclusa perché non ci sono record corrispondenti nella Tabella2 .
Ogni volta che formulo una query, la mia prima scelta è INNER JOIN. OUTER JOIN arriva solo quando i requisiti lo richiedono.
Esistono due sintassi INNER JOIN supportate in T-SQL:SQL-92 e SQL-89.
La prima sintassi di join che ho imparato è stata SQL-89. Quando finalmente è arrivato SQL-92, ho pensato che fosse troppo lungo. Ho anche pensato che l'output fosse lo stesso, perché preoccuparsi di digitare più parole chiave? Un progettista grafico di query aveva il codice generato SQL-92 e l'ho cambiato di nuovo in SQL-89. Ma oggi preferisco SQL-92 anche se devo digitare di più. Ecco perché:
I motivi di cui sopra sono miei. Potresti avere le tue ragioni per cui preferisci SQL-92 o perché lo odi. Mi chiedo quali siano queste ragioni. Fammi sapere nella sezione Commenti qui sotto.
Ma non possiamo concludere questo articolo senza esempi e spiegazioni.
Ecco un esempio di 2 tabelle unite insieme utilizzando INNER JOIN nella sintassi SQL-92.
Specifica solo le colonne di cui hai bisogno. Nell'esempio sopra, sono specificate 4 colonne. So che è troppo lungo di SELECT * ma tienilo a mente:è la migliore pratica.
Notare anche l'uso di alias di tabella. Sia il Prodotto e Sottocategoria di prodotto le tabelle hanno una colonna denominata [Nome ]. Se non specifichi l'alias, verrà generato un errore.
Nel frattempo, ecco la sintassi SQL-89 equivalente:
Sono gli stessi tranne che per la condizione di join mista nella clausola WHERE con una parola chiave AND. Ma sotto il cofano, sono davvero la stessa cosa? Esaminiamo il set di risultati, STATISTICS IO e il Piano di esecuzione.
Vedi il set di risultati di 9 record:
Non sono solo i risultati, ma anche le risorse richieste da SQL Server sono le stesse.
Vedi le letture logiche:
Infine, il piano di esecuzione rivela lo stesso piano di query per entrambe le query quando i loro QueryPlanHashes sono uguali. Notare anche le operazioni evidenziate nel diagramma:
Sulla base dei risultati, l'elaborazione delle query di SQL Server è la stessa, indipendentemente dal fatto che si tratti di SQL-92 o SQL-89. Ma come ho detto, la chiarezza in SQL-92 è molto migliore per me.
La figura 7 mostra anche un Nested Loop Join utilizzato nel piano. Come mai? Il set di risultati è piccolo.
Controlla la query di seguito utilizzando 3 tabelle unite.
Puoi anche unire 2 tavoli usando 2 chiavi per metterlo in relazione. Dai un'occhiata all'esempio qui sotto. Utilizza 2 condizioni di unione con un operatore AND.
Nell'esempio seguente, il Prodotto la tabella ha 9 record:un piccolo set. La tabella unita è SalesOrderDetail – un grande set. Query Optimizer utilizzerà un Nested Loop Join, come mostrato nella Figura 8.
L'esempio seguente utilizza un Merge Join perché entrambe le tabelle di input sono ordinate per SalesOrderID.
L'esempio seguente utilizzerà un Hash Join:
Nell'esempio seguente, il Addetto alle vendite la tabella ha un indice ColumnStore non cluster su TerritoryID colonna. Query Optimizer ha deciso un join del ciclo nidificato, come mostrato nella Figura 11.
Considera questa affermazione con una sottoquery nidificata:
Gli stessi risultati possono venire fuori se lo modifichi in un INNER JOIN, come di seguito:
Un altro modo per riscriverlo è utilizzare una tabella derivata come origine tabella per INNER JOIN:
Tutte e 3 le query generano gli stessi 48 record.
La query seguente utilizza un ciclo annidato:
Se vuoi forzarlo a un hash join, ecco cosa succede:
Tuttavia, tieni presente che STATISTICS IO mostra che le prestazioni peggiorano quando lo forzi a un hash join.
Nel frattempo, la query seguente utilizza un Merge Join:
Ecco cosa diventa quando lo forzi a un ciclo nidificato:
Dopo aver verificato l'IO di STATISTICHE di entrambi, forzarlo a un ciclo nidificato richiede più risorse per elaborare la query:
Pertanto, l'utilizzo dei suggerimenti di unione dovrebbe essere l'ultima risorsa quando si ottimizzano le prestazioni. Lascia che sia il tuo SQL Server a gestirlo per te.
Puoi anche utilizzare INNER JOIN in un'istruzione UPDATE. Ecco un esempio:
Poiché è possibile utilizzare un join in un AGGIORNAMENTO, perché non provarlo utilizzando DELETE e INSERT?
Allora, qual è il problema di SQL join?
Nel frattempo, questo post ha mostrato 10 esempi di INNER JOIN. Non sono solo codici di esempio. Alcuni di essi includono anche un'ispezione di come funziona il codice dall'interno verso l'esterno. Non è solo per aiutarti a programmare, ma per aiutarti a essere consapevole delle prestazioni. Alla fine della giornata, i risultati non dovrebbero essere solo corretti ma anche consegnati rapidamente.
Non abbiamo ancora finito. Il prossimo articolo tratterà delle OUTER JOINS. Resta sintonizzato.
I join SQL consentono di recuperare e combinare dati da più tabelle. Guarda questo video per saperne di più sui join SQL.SQL JOIN e sottoquery
Join e tabelle derivate
FROM table1 a
INNER JOIN (SELECT y.column3 from table2 x
INNER JOIN table3 y on x.column1 = y.column1) b ON a.col1 = b.col2
Come SQL Server elabora i join
Perché dobbiamo preoccuparci di questo?
Suggerisci unisciti
<join type> <join hint> JOIN <table source> [<alias>] ON <join condition>
Tutto su INNER JOIN
Sintassi INNER JOIN
UNIONE INTERNA SQL-92
FROM <table source1> [<alias1>]
INNER JOIN <table source2> [<alias2>] ON <join condition1>
[INNER JOIN <table source3> [<alias3>] ON <join condition2>
INNER JOIN <table sourceN> [<aliasN>] ON <join conditionN>]
[WHERE <condition>]
UNIONE INTERNA SQL-89
FROM <table source1> [alias1], <table source2> [alias2] [, <table source3> [alias3], <table sourceN> [aliasN]]
WHERE (<join condition1>)
[AND (<join condition2>)
AND (<join condition3>)
AND (<join conditionN>)]
Quale sintassi INNER JOIN è migliore?
10 Esempi di INNER JOIN
1. Unire 2 Tabelle
-- Display Vests, Helmets, and Light products
USE AdventureWorks
GO
SELECT
p.ProductID
,P.Name AS [Product]
,ps.ProductSubcategoryID
,ps.Name AS [ProductSubCategory]
FROM Production.Product p
INNER JOIN Production.ProductSubcategory ps ON P.ProductSubcategoryID = ps.ProductSubcategoryID
WHERE P.ProductSubcategoryID IN (25, 31, 33); -- for vest, helmet, and light
-- product subcategories
-- Display Vests, Helmets, and Light products
USE AdventureWorks
GO
SELECT
p.ProductID
,P.Name AS [Product]
,ps.ProductSubcategoryID
,ps.Name AS [ProductSubCategory]
FROM Production.Product p, Production.ProductSubcategory ps
WHERE P.ProductSubcategoryID = ps.ProductSubcategoryID
AND P.ProductSubcategoryID IN (25, 31, 33);
2. Unire più tabelle
-- Get the total number of orders per Product Category
USE AdventureWorks
GO
SELECT
ps.Name AS ProductSubcategory
,SUM(sod.OrderQty) AS TotalOrders
FROM Production.Product p
INNER JOIN Sales.SalesOrderDetail sod ON P.ProductID = sod.ProductID
INNER JOIN Sales.SalesOrderHeader soh ON sod.SalesOrderID = soh.SalesOrderID
INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID
WHERE soh.OrderDate BETWEEN '1/1/2014' AND '12/31/2014'
AND p.ProductSubcategoryID IN (1,2)
GROUP BY ps.Name
HAVING ps.Name IN ('Mountain Bikes', 'Road Bikes')
3. Partecipazione composita
SELECT
a.column1
,b.column1
,b.column2
FROM Table1 a
INNER JOIN Table2 b ON a.column1 = b.column1 AND a.column2 = b.column2
4. INNER JOIN Utilizzo di un collegamento fisico a loop nidificato
USE AdventureWorks
GO
SELECT
sod.SalesOrderDetailID
,sod.ProductID
,P.Name
,P.ProductNumber
,sod.OrderQty
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON sod.ProductID = p.ProductID
WHERE P.ProductSubcategoryID IN(25, 31, 33);
5. INNER JOIN Utilizzo di un join fisico di unione
SELECT
soh.SalesOrderID
,soh.OrderDate
,sod.SalesOrderDetailID
,sod.ProductID
,sod.LineTotal
FROM Sales.SalesOrderHeader soh
INNER JOIN sales.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
6. INNER JOIN Utilizzo di un join fisico hash
SELECT
s.Name AS Store
,SUM(soh.TotalDue) AS TotalSales
FROM Sales.SalesOrderHeader soh
INNER JOIN Sales.Store s ON soh.SalesPersonID = s.SalesPersonID
GROUP BY s.Name
7. INNER JOIN Utilizzo di Adaptive Physical Join
SELECT
sp.BusinessEntityID
,sp.SalesQuota
,st.Name AS Territory
FROM Sales.SalesPerson sp
INNER JOIN Sales.SalesTerritory st ON sp.TerritoryID = st.TerritoryID
WHERE sp.TerritoryID BETWEEN 1 AND 5
8. Due modi per riscrivere una sottoquery in un INNER JOIN
SELECT [SalesOrderID], [OrderDate], [ShipDate], [CustomerID]
FROM Sales.SalesOrderHeader
WHERE [CustomerID] IN (SELECT [CustomerID] FROM Sales.Customer
WHERE PersonID IN (SELECT BusinessEntityID FROM Person.Person
WHERE lastname LIKE N'I%' AND PersonType='SC'))
SELECT o.[SalesOrderID], o.[OrderDate], o.[ShipDate], o.[CustomerID]
FROM Sales.SalesOrderHeader o
INNER JOIN Sales.Customer c on o.CustomerID = c.CustomerID
INNER JOIN Person.Person p ON c.PersonID = p.BusinessEntityID
WHERE p.PersonType = 'SC'
AND p.lastname LIKE N'I%'
SELECT o.[SalesOrderID], o.[OrderDate], o.[ShipDate], o.[CustomerID]
FROM Sales.SalesOrderHeader o
INNER JOIN (SELECT c.CustomerID, P.PersonType, P.LastName
FROM Sales.Customer c
INNER JOIN Person.Person p ON c.PersonID = P.BusinessEntityID
WHERE p.PersonType = 'SC'
AND p.LastName LIKE N'I%') AS q ON o.CustomerID = q.CustomerID
9. Utilizzo dei suggerimenti per l'adesione
SELECT
sod.SalesOrderDetailID
,sod.ProductID
,P.Name
,P.ProductNumber
,sod.OrderQty
FROM Sales.SalesOrderDetail sod
INNER JOIN Production.Product p ON sod.ProductID = p.ProductID
WHERE P.ProductSubcategoryID IN(25, 31, 33);
SELECT
sod.SalesOrderDetailID
,sod.ProductID
,P.Name
,P.ProductNumber
,sod.OrderQty
FROM Sales.SalesOrderDetail sod
INNER HASH JOIN Production.Product p ON sod.ProductID = p.ProductID
WHERE P.ProductSubcategoryID IN(25, 31, 33);
SELECT
soh.SalesOrderID
,soh.OrderDate
,sod.SalesOrderDetailID
,sod.ProductID
,sod.LineTotal
FROM Sales.SalesOrderHeader soh
INNER JOIN sales.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
SELECT
soh.SalesOrderID
,soh.OrderDate
,sod.SalesOrderDetailID
,sod.ProductID
,sod.LineTotal
FROM Sales.SalesOrderHeader soh
INNER LOOP JOIN sales.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
10. Utilizzo di INNER JOIN in UPDATE
UPDATE Sales.SalesOrderHeader
SET ShipDate = getdate()
FROM Sales.SalesOrderHeader o
INNER JOIN Sales.Customer c on o.CustomerID = c.CustomerID
INNER JOIN Person.Person p ON c.PersonID = p.BusinessEntityID
WHERE p.PersonType = 'SC'
Asporto SQL Join e INNER JOIN
Vedi anche