Tham gia bên trong, tham gia bên ngoài, tham gia chéo? Điều gì mang lại?
Đó là một câu hỏi hợp lệ. Tôi đã từng thấy một mã Visual Basic với mã T-SQL được nhúng trong đó. Mã VB truy xuất các bản ghi bảng với nhiều câu lệnh SELECT, một câu lệnh SELECT * trên mỗi bảng. Sau đó, nó kết hợp nhiều tập hợp kết quả thành một tập hợp bản ghi. Phi lý?
Đối với các nhà phát triển trẻ, những người đã làm điều đó, thì không. Nhưng khi họ yêu cầu tôi đánh giá lý do tại sao hệ thống chạy chậm, vấn đề đó là vấn đề đầu tiên khiến tôi chú ý. Đúng rồi. Họ chưa bao giờ nghe nói về các phép nối SQL. Công bằng mà nói, họ trung thực và cởi mở với các đề xuất.
Làm thế nào để bạn mô tả các phép nối SQL? Có lẽ, bạn còn nhớ một bài hát - Imagine của John Lennon:
Bạn có thể nói tôi là một người mơ mộng, nhưng tôi không phải là người duy nhất.
Tôi hy vọng một ngày nào đó bạn sẽ tham gia cùng chúng tôi và thế giới sẽ hòa làm một.
Trong ngữ cảnh của bài hát, tham gia là hợp nhất. Trong cơ sở dữ liệu SQL, kết hợp các bản ghi của 2 hoặc nhiều bảng thành một tập hợp kết quả tạo thành một phép nối .
Bài viết này là phần mở đầu của loạt bài gồm 3 phần nói về các phép nối trong SQL:
- THAM GIA INNER
- THAM GIA NGOÀI TRỜI, bao gồm LEFT, RIGHT và FULL
- THAM GIA CROSS
Nhưng trước khi chúng ta bắt đầu thảo luận về INNER JOIN, hãy mô tả chung về các phép nối.
Tìm hiểu thêm về SQL JOIN
Các phép nối xuất hiện ngay sau mệnh đề FROM. Ở dạng đơn giản nhất, nó trông giống như sử dụng tiêu chuẩn 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>]
Hãy mô tả những thứ hàng ngày xung quanh THAM GIA.
Nguồn bảng
Bạn có thể thêm tối đa 256 nguồn bảng, theo Microsoft. Tất nhiên, nó phụ thuộc vào tài nguyên máy chủ của bạn. Tôi chưa bao giờ tham gia nhiều hơn 10 bảng trong đời, chưa kể 256. Dù sao, nguồn bảng có thể là bất kỳ nguồn nào sau đây:
- Bảng
- Xem
- Bảng hoặc xem từ đồng nghĩa
- Biến bảng
- Hàm giá trị bảng
- Bảng có nguồn gốc
Bí danh bảng
Bí danh là tùy chọn, nhưng nó rút ngắn mã của bạn và giảm thiểu việc nhập. Nó cũng giúp bạn tránh lỗi khi tên cột tồn tại trong hai hoặc nhiều bảng được sử dụng trong CHỌN, CẬP NHẬT, CHÈN hoặc XÓA. Nó cũng bổ sung thêm sự rõ ràng cho mã của bạn. Đây là tùy chọn, nhưng tôi khuyên bạn nên sử dụng bí danh. (Trừ khi bạn thích nhập các nguồn bảng theo tên.)
Điều kiện tham gia
Từ khóa ON đứng trước điều kiện nối có thể là một phép nối đơn hoặc cột 2 khóa từ 2 bảng được nối. Hoặc nó có thể là một phép nối tổng hợp sử dụng nhiều hơn 2 cột chính. Nó xác định các bảng có liên quan như thế nào.
Tuy nhiên, chúng tôi chỉ sử dụng điều kiện tham gia cho các phép nối INNER và OUTER. Sử dụng nó trên CROSS JOIN sẽ gây ra lỗi.
Vì các điều kiện kết hợp xác định các mối quan hệ, chúng cần các toán tử.
Phổ biến nhất của các toán tử điều kiện nối là toán tử bình đẳng (=). Các toán tử khác như> hoặc
Hầu hết các phép nối có thể được viết lại dưới dạng truy vấn con và ngược lại. Hãy xem bài viết này để tìm hiểu thêm về truy vấn con so với kết hợp.
Sử dụng các bảng dẫn xuất trong một phép nối sẽ giống như sau:
Nó đang kết hợp từ kết quả của một câu lệnh SELECT khác và nó hoàn toàn hợp lệ.
Bạn sẽ có nhiều ví dụ hơn, nhưng hãy giải quyết một điều cuối cùng về SQL JOINS. Đó là cách các quy trình Trình tối ưu hóa truy vấn của SQL Server tham gia.
Để hiểu quy trình hoạt động như thế nào, bạn cần biết về hai loại hoạt động liên quan:
Một từ:Hiệu suất.
Một điều là biết cách tạo các truy vấn với các phép nối để tạo ra kết quả chính xác. Một cách khác là làm cho nó chạy càng nhanh càng tốt. Bạn phải quan tâm nhiều hơn đến điều này nếu bạn muốn có danh tiếng tốt với người dùng của mình.
Vì vậy, bạn cần tìm kiếm điều gì trong Kế hoạch thực thi cho những hoạt động hợp lý này?
Các gợi ý tham gia là mới trong SQL Server 2019. Khi bạn sử dụng nó trong các liên kết của mình, nó sẽ yêu cầu trình tối ưu hóa truy vấn ngừng quyết định điều gì là tốt nhất cho truy vấn. Bạn là ông chủ khi nói đến tham gia vật lý để sử dụng.
Bây giờ dừng lại, ngay tại đó. Sự thật là, trình tối ưu hóa truy vấn thường chọn kết hợp vật lý tốt nhất cho truy vấn của bạn. Nếu bạn không biết mình đang làm gì, đừng sử dụng các gợi ý tham gia.
Các gợi ý khả thi mà bạn có thể chỉ định là LOOP, MERGE, HASH hoặc REMOTE.
Tôi chưa sử dụng gợi ý tham gia, nhưng đây là cú pháp:
INNER JOIN trả về các hàng có bản ghi phù hợp trong cả hai bảng, dựa trên một điều kiện. Nó cũng là kết hợp mặc định nếu bạn không chỉ định từ khóa INNER:
Như bạn thấy, các hàng phù hợp từ Table1 và Table2 được trả lại bằng Key1 như điều kiện tham gia. Bảng1 ghi lại có Key1 =‘C’ bị loại trừ vì không có bản ghi nào phù hợp trong Table2 .
Bất cứ khi nào tôi tạo một truy vấn, lựa chọn đầu tiên của tôi là INNER JOIN. OUTER JOIN xuất hiện khi các yêu cầu chỉ định nó.
Có hai cú pháp INNER JOIN được hỗ trợ trong T-SQL:SQL-92 và SQL-89.
Cú pháp nối đầu tiên tôi học được là SQL-89. Khi SQL-92 cuối cùng đã đến, tôi nghĩ nó quá dài. Tôi cũng nghĩ rằng đầu ra là như nhau, tại sao phải gõ thêm từ khóa? Một nhà thiết kế truy vấn đồ họa đã tạo mã SQL-92 và tôi đã thay đổi nó trở lại SQL-89. Nhưng ngày nay, tôi thích SQL-92 hơn ngay cả khi tôi phải nhập nhiều hơn. Đây là lý do tại sao:
Những lý do trên là của tôi. Bạn có thể có lý do tại sao bạn thích SQL-92 hoặc tại sao bạn ghét nó. Tôi tự hỏi những lý do đó là gì. Hãy cho tôi biết trong phần Nhận xét bên dưới.
Nhưng chúng tôi không thể kết thúc bài viết này nếu không có các ví dụ và giải thích.
Dưới đây là ví dụ về 2 bảng được kết hợp với nhau bằng cách sử dụng INNER JOIN trong cú pháp SQL-92.
Bạn chỉ xác định các cột mà bạn cần. Trong ví dụ trên, 4 cột được chỉ định. Tôi biết nó quá dài dòng so với SELECT * nhưng hãy ghi nhớ điều này:đó là phương pháp hay nhất.
Cũng lưu ý việc sử dụng bí danh bảng. Cả Sản phẩm và ProductSubcategory bảng có một cột có tên [ Tên ]. Nếu bạn không chỉ định bí danh, lỗi sẽ được kích hoạt.
Trong khi đó, đây là cú pháp SQL-89 tương đương:
Chúng giống nhau ngoại trừ điều kiện nối được trộn lẫn trong mệnh đề WHERE với từ khóa AND. Nhưng dưới mui xe, chúng có thực sự giống nhau? Hãy cùng kiểm tra tập hợp kết quả, IO THỐNG KÊ và Kế hoạch thực thi.
Xem bộ kết quả gồm 9 bản ghi:
Đó không chỉ là kết quả mà các tài nguyên được SQL Server yêu cầu cũng giống nhau.
Xem các bài đọc logic:
Cuối cùng, Kế hoạch thực thi tiết lộ cùng một kế hoạch truy vấn cho cả hai truy vấn khi QueryPlanHashing bằng nhau. Cũng lưu ý các hoạt động được đánh dấu trong sơ đồ:
Dựa trên những phát hiện, quá trình xử lý truy vấn SQL Server giống nhau, cho dù đó là SQL-92 hay SQL-89. Nhưng như tôi đã nói, sự rõ ràng trong SQL-92 đối với tôi tốt hơn nhiều.
Hình 7 cũng cho thấy một phép nối vòng lặp lồng nhau được sử dụng trong kế hoạch. Tại sao? Tập hợp kết quả là nhỏ.
Kiểm tra truy vấn bên dưới bằng cách sử dụng 3 bảng đã kết hợp.
Bạn cũng có thể tham gia 2 bảng bằng cách sử dụng 2 phím để liên kết nó. Kiểm tra các mẫu dưới đây. Nó sử dụng 2 điều kiện kết hợp với toán tử AND.
Trong ví dụ bên dưới, Sản phẩm bảng có 9 bản ghi - một tập hợp nhỏ. Bảng đã tham gia là SalesOrderDetail - một bộ lớn. Trình tối ưu hoá Truy vấn sẽ sử dụng Kết nối vòng lặp lồng nhau, như thể hiện trong Hình 8.
Ví dụ bên dưới sử dụng Kết hợp Hợp nhất vì cả hai bảng đầu vào được sắp xếp theo SalesOrderID.
Ví dụ sau sẽ sử dụng Hash Join:
Trong ví dụ dưới đây, Người bán hàng bảng có Chỉ mục cửa hàng không phân cụm trên TerritoryID cột. Trình tối ưu hóa truy vấn đã quyết định về phép nối vòng lặp lồng nhau, như thể hiện trong Hình 11.
Hãy xem xét câu lệnh này với một truy vấn con lồng nhau:
Kết quả tương tự có thể xuất hiện nếu bạn thay đổi nó thành INNER JOIN, như sau:
Một cách khác để viết lại nó là sử dụng bảng dẫn xuất làm nguồn bảng cho INNER JOIN:
Cả 3 truy vấn đều xuất ra 48 bản ghi giống nhau.
Truy vấn sau sử dụng Vòng lặp lồng nhau:
Nếu bạn muốn buộc nó tham gia Hash, đây là những gì sẽ xảy ra:
Tuy nhiên, lưu ý rằng STATISTICS IO cho thấy rằng hiệu suất sẽ trở nên tồi tệ khi bạn buộc nó phải tham gia Hash.
Trong khi đó, truy vấn bên dưới sử dụng Kết hợp Hợp nhất:
Đây là những gì nó sẽ trở thành khi bạn buộc nó vào một Vòng lặp lồng nhau:
Khi kiểm tra IO THỐNG KÊ của cả hai, buộc nó vào Vòng lặp lồng nhau yêu cầu nhiều tài nguyên hơn để xử lý truy vấn:
Vì vậy, sử dụng gợi ý tham gia nên là phương sách cuối cùng của bạn khi điều chỉnh hiệu suất. Hãy để Máy chủ SQL của bạn xử lý nó cho bạn.
Bạn cũng có thể sử dụng INNER JOIN trong câu lệnh CẬP NHẬT. Đây là một ví dụ:
Vì có thể sử dụng kết hợp trong CẬP NHẬT, tại sao bạn không thử sử dụng XÓA và CHÈN?
Vậy, vấn đề lớn về tham gia SQL là gì?
Trong khi đó, bài đăng này cho thấy 10 ví dụ về INNER JOIN. Nó không chỉ là mã mẫu. Một số trong số chúng cũng bao gồm việc kiểm tra cách mã hoạt động từ trong ra ngoài. Nó không chỉ giúp bạn viết mã mà còn giúp bạn lưu tâm đến hiệu suất. Vào cuối ngày, kết quả không chỉ chính xác mà còn được phân phối nhanh chóng.
Chúng tôi vẫn chưa xong. Bài tiếp theo sẽ đề cập đến THAM GIA NGOÀI TRỜI. Hãy theo dõi.
SQL Joins cho phép bạn tìm nạp và kết hợp dữ liệu từ nhiều bảng. Xem video này để tìm hiểu thêm về SQL Joins. SQL JOIN so với Truy vấn con
Bảng tham gia và bảng có nguồn gốc
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
Cách máy chủ SQL xử lý tham gia
Tại sao chúng ta cần phải làm phiền với điều này?
Gợi ý tham gia
<join type> <join hint> JOIN <table source> [<alias>] ON <join condition>
Giới thiệu về INNER JOIN
Cú pháp INNER JOIN
THAM GIA BÊN TRONG 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>]
THAM GIA INNER 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>)]
Cú pháp INNER JOIN nào tốt hơn?
10 Ví dụ về INNER JOIN
1. Tham gia 2 bảng
-- 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. Tham gia nhiều bảng
-- 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. Tham gia tổng hợp
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. THAM GIA INNER Sử dụng Tham gia Vật lý Vòng lặp lồng nhau
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. THAM GIA INNER Sử dụng Hợp nhất Tham gia Vật lý
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 THAM GIA bằng cách sử dụng một tham gia vật lý băm
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. THAM GIA INNER Sử dụng Tham gia Vật lý Thích ứng
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. Hai cách để viết lại một truy vấn con thành một 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. Sử dụng Gợi ý Tham gia
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. Sử dụng INNER JOIN trong 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'
Kết nối SQL và Kết quả tham gia INNER
Xem thêm