Gabung dalam, gabung luar, gabung silang? Apa yang memberi?
Ini pertanyaan yang valid. Saya pernah melihat kode Visual Basic dengan kode T-SQL yang tertanam di dalamnya. Kode VB mengambil record tabel dengan beberapa pernyataan SELECT, satu SELECT * per tabel. Kemudian, ini menggabungkan beberapa set hasil menjadi satu set rekaman. Tidak masuk akal?
Bagi para pengembang muda yang melakukannya, ternyata tidak. Tetapi ketika mereka meminta saya untuk mengevaluasi mengapa sistemnya lambat, masalah itu adalah yang pertama menarik perhatian saya. Betul sekali. Mereka tidak pernah mendengar tentang SQL bergabung. Dalam keadilan bagi mereka, mereka jujur dan terbuka terhadap saran.
Bagaimana Anda menggambarkan gabungan SQL? Mungkin, Anda ingat satu lagu – Bayangkan oleh John Lennon:
Anda mungkin mengatakan saya seorang pemimpi, tapi saya bukan satu-satunya.
Saya harap suatu hari nanti Anda akan bergabung dengan kami, dan dunia akan menjadi satu.
Dalam konteks lagu, bergabung adalah menyatukan. Dalam database SQL, menggabungkan catatan dari 2 tabel atau lebih menjadi satu kumpulan hasil membentuk gabungan .
Artikel ini adalah awal dari seri 3 bagian yang berbicara tentang gabungan SQL:
- GABUNG DALAM
- OUTER JOIN, yang mencakup KIRI, KANAN, dan PENUH
- GABUNG LINTAS
Namun sebelum kita mulai membahas INNER JOIN, mari kita uraikan join secara umum.
Selengkapnya Tentang SQL JOIN
Gabungan muncul tepat setelah klausa FROM. Dalam bentuknya yang paling sederhana, sepertinya menggunakan standar 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>]
Mari kita jelaskan hal-hal sehari-hari seputar JOIN.
Sumber Tabel
Anda dapat menambahkan hingga 256 sumber tabel, menurut Microsoft. Tentu saja, itu tergantung pada sumber daya server Anda. Saya tidak pernah bergabung lebih dari 10 tabel dalam hidup saya, belum lagi 256. Bagaimanapun, sumber tabel dapat berupa salah satu dari berikut:
- Tabel
- Lihat
- Meja atau melihat sinonim
- Variabel tabel
- Fungsi bernilai tabel
- Tabel turunan
Alias Tabel
Alias adalah opsional, tetapi memperpendek kode Anda dan meminimalkan pengetikan. Ini juga membantu Anda menghindari kesalahan saat nama kolom ada di dua atau lebih tabel yang digunakan dalam SELECT, UPDATE, INSERT, atau DELETE. Ini juga menambah kejelasan pada kode Anda. Ini opsional, tetapi saya sarankan menggunakan alias. (Kecuali Anda suka mengetik sumber tabel berdasarkan nama.)
Kondisi Bergabung
Kata kunci ON mendahului kondisi gabung yang dapat berupa kolom gabungan tunggal atau kolom 2 kunci dari 2 tabel yang digabungkan. Atau bisa juga gabungan gabungan menggunakan lebih dari 2 kolom kunci. Ini mendefinisikan bagaimana tabel terkait.
Namun, kami menggunakan kondisi join hanya untuk INNER dan OUTER join. Menggunakannya pada CROSS JOIN akan memicu kesalahan.
Karena kondisi join menentukan hubungan, mereka membutuhkan operator.
Operator kondisi gabungan yang paling umum adalah operator persamaan (=). Operator lain seperti> atau
Sebagian besar gabungan dapat ditulis ulang sebagai subkueri dan sebaliknya. Lihat artikel ini untuk mempelajari lebih lanjut tentang subkueri dibandingkan dengan bergabung.
Menggunakan tabel turunan dalam gabungan terlihat seperti ini:
Itu bergabung dari hasil pernyataan SELECT lain, dan itu benar-benar valid.
Anda akan memiliki lebih banyak contoh, tetapi mari kita bahas satu hal terakhir tentang SQL JOINS. Ini adalah bagaimana proses Pengoptimal Kueri SQL Server bergabung.
Untuk memahami cara kerja proses, Anda perlu mengetahui tentang dua jenis operasi yang terlibat:
Satu kata:Performa.
Satu hal adalah mengetahui cara membentuk kueri dengan gabungan untuk menghasilkan hasil yang benar. Satu lagi adalah membuatnya berjalan secepat mungkin. Anda harus ekstra hati-hati tentang hal ini jika Anda ingin reputasi yang baik dengan pengguna Anda.
Jadi, apa yang perlu Anda perhatikan dalam Rencana Eksekusi untuk operasi logis ini?
Petunjuk bergabung adalah hal baru di SQL Server 2019. Saat Anda menggunakannya dalam bergabung, ini memberi tahu pengoptimal kueri untuk berhenti memutuskan apa yang terbaik untuk kueri. Anda adalah bosnya dalam hal gabungan fisik untuk digunakan.
Sekarang berhenti, di sana. Sebenarnya, pengoptimal kueri biasanya memilih gabungan fisik terbaik untuk kueri Anda. Jika Anda tidak tahu apa yang Anda lakukan, jangan gunakan petunjuk bergabung.
Petunjuk yang mungkin dapat Anda tentukan adalah LOOP, MERGE, HASH, atau REMOTE.
Saya belum pernah menggunakan petunjuk bergabung, tapi begini sintaksnya:
INNER JOIN mengembalikan baris dengan catatan yang cocok di kedua tabel, berdasarkan kondisi. Ini juga merupakan gabungan default jika Anda tidak menentukan kata kunci INNER:
Seperti yang Anda lihat, mencocokkan baris dari Tabel1 dan Tabel2 dikembalikan menggunakan Key1 sebagai syarat bergabung. Tabel1 catatan memiliki Key1 ='C' dikecualikan karena tidak ada catatan yang cocok di Tabel2 .
Setiap kali saya membuat kueri, pilihan pertama saya adalah INNER JOIN. OUTER JOIN datang ketika persyaratan hanya menentukannya.
Ada dua sintaks INNER JOIN yang didukung di T-SQL:SQL-92 dan SQL-89.
Sintaks join pertama yang saya pelajari adalah SQL-89. Ketika SQL-92 akhirnya tiba, saya pikir itu terlalu panjang. Saya juga berpikir karena outputnya sama, mengapa repot-repot mengetik lebih banyak kata kunci? Seorang desainer kueri grafis memiliki kode yang dihasilkan SQL-92, dan saya mengubahnya kembali ke SQL-89. Tapi hari ini, saya lebih suka SQL-92 bahkan jika saya harus mengetik lebih banyak. Inilah alasannya:
Alasan di atas adalah milik saya. Anda mungkin memiliki alasan mengapa Anda lebih memilih SQL-92 atau mengapa Anda membencinya. Aku ingin tahu apa alasan-alasan itu. Beri tahu saya di bagian Komentar di bawah.
Tapi kita tidak bisa mengakhiri artikel ini tanpa contoh dan penjelasan.
Berikut ini contoh 2 tabel yang digabungkan menggunakan INNER JOIN dalam sintaks SQL-92.
Anda hanya menentukan kolom yang Anda butuhkan. Dalam contoh di atas, 4 kolom ditentukan. Saya tahu ini terlalu panjang dari SELECT * tetapi ingatlah ini:ini adalah praktik terbaik.
Perhatikan juga penggunaan alias tabel. Baik Produk dan Subkategori Produk tabel memiliki kolom bernama [Nama ]. Jika Anda tidak menentukan alias, kesalahan akan dipicu.
Sementara itu, berikut sintaks SQL-89 yang setara:
Mereka sama kecuali untuk kondisi join yang dicampur dalam klausa WHERE dengan kata kunci AND. Tetapi di bawah tenda, apakah mereka benar-benar sama? Mari kita periksa kumpulan hasil, STATISTICS IO, dan Execution Plan.
Lihat kumpulan hasil dari 9 catatan:
Bukan hanya hasil, tetapi sumber daya yang dibutuhkan oleh SQL Server juga sama.
Lihat bacaan logisnya:
Terakhir, Rencana Eksekusi mengungkapkan rencana kueri yang sama untuk kedua kueri saat QueryPlanHashes adalah sama. Perhatikan juga operasi yang disorot dalam diagram:
Berdasarkan temuan, pemrosesan query SQL Server adalah sama, apakah itu SQL-92 atau SQL-89. Tapi seperti yang saya katakan, kejelasan dalam SQL-92 jauh lebih baik bagi saya.
Gambar 7 juga menunjukkan Gabung Loop Bersarang yang digunakan dalam rencana. Mengapa? Kumpulan hasil kecil.
Lihat kueri di bawah ini menggunakan 3 tabel gabungan.
Anda juga dapat menggabungkan 2 tabel menggunakan 2 kunci untuk menghubungkannya. Lihat contoh di bawah ini. Ini menggunakan 2 kondisi bergabung dengan operator AND.
Pada contoh di bawah, Produk tabel memiliki 9 catatan – satu set kecil. Tabel yang digabungkan adalah SalesOrderDetail - satu set besar. Query Optimizer akan menggunakan Nested Loop Join, seperti yang ditunjukkan pada Gambar 8.
Contoh di bawah ini menggunakan Gabung Gabung karena kedua tabel input diurutkan berdasarkan SalesOrderID.
Contoh berikut akan menggunakan Hash Join:
Pada contoh di bawah ini, SalesPerson tabel memiliki Indeks ColumnStore Non-cluster di TerritoryID kolom. Pengoptimal Kueri memutuskan Penggabungan Loop Bersarang, seperti yang ditunjukkan pada Gambar 11.
Pertimbangkan pernyataan ini dengan subquery bersarang:
Hasil yang sama bisa keluar jika Anda mengubahnya menjadi INNER JOIN, seperti di bawah ini:
Cara lain untuk menulis ulang adalah dengan menggunakan tabel turunan sebagai sumber tabel untuk INNER JOIN:
Ketiga kueri menghasilkan 48 record yang sama.
Kueri berikut menggunakan Nested Loop:
Jika Anda ingin memaksanya untuk bergabung dengan Hash, inilah yang terjadi:
Namun, perhatikan bahwa STATISTICS IO menunjukkan bahwa kinerja akan menjadi buruk saat Anda memaksanya untuk bergabung dengan Hash.
Sedangkan query di bawah ini menggunakan Merge Join:
Begini jadinya jika Anda memaksanya ke Nested Loop:
Setelah memeriksa STATISTICS IO dari keduanya, memaksanya ke Nested Loop memerlukan lebih banyak sumber daya untuk memproses kueri:
Jadi, menggunakan petunjuk bergabung harus menjadi pilihan terakhir Anda saat mengutak-atik kinerja. Biarkan SQL Server Anda menanganinya untuk Anda.
Anda juga dapat menggunakan INNER JOIN dalam pernyataan UPDATE. Ini contohnya:
Karena dimungkinkan untuk menggunakan gabungan dalam UPDATE, mengapa tidak mencobanya menggunakan DELETE dan INSERT?
Jadi, apa hebatnya bergabung dengan SQL?
Sementara itu, postingan ini menunjukkan 10 contoh INNER JOIN. Ini bukan hanya kode sampel. Beberapa di antaranya juga mencakup pemeriksaan cara kerja kode dari dalam ke luar. Ini bukan hanya untuk membantu Anda membuat kode tetapi untuk membantu Anda memperhatikan kinerja. Pada akhirnya, hasilnya tidak hanya harus benar tetapi juga disampaikan dengan cepat.
Kami belum selesai. Artikel selanjutnya akan membahas OUTER JOINS. Pantau terus.
SQL Joins memungkinkan Anda mengambil dan menggabungkan data dari lebih dari satu tabel. Tonton video ini untuk mempelajari lebih lanjut tentang SQL Joins.SQL GABUNG vs. Subkueri
Gabung dan Turunkan Tabel
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
Bagaimana Proses SQL Server Bergabung
Mengapa Kita Perlu Repot Dengan Ini?
Petunjuk Bergabung
<join type> <join hint> JOIN <table source> [<alias>] ON <join condition>
Semua Tentang INNER JOIN
Sintaks INNER JOIN
SQL-92 INNER GABUNG
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>]
SQL-89 INNER GABUNG
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>)]
Sintaks INNER JOIN mana yang Lebih Baik?
10 Contoh INNER JOIN
1. Bergabung dengan 2 Tabel
-- 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. Bergabung dengan Beberapa Tabel
-- 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. Gabungan Gabungan
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 Menggunakan Penggabungan Fisik Loop Bersarang
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 Menggunakan Gabung Gabung Fisik
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 Menggunakan Hash Physical Join
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 Menggunakan 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. Dua Cara untuk Menulis Ulang Subquery ke 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. Menggunakan Petunjuk Bergabung
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. Menggunakan INNER JOIN di 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'
SQL Join dan INNER JOIN Takeaways
Lihat juga