Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Khái niệm cơ bản về tham gia bên trong máy chủ SQL với các ví dụ

Giới thiệu

T-SQL cho phép chúng tôi kết hợp các bản ghi từ nhiều hơn một bảng và trả về chúng dưới dạng một tập kết quả duy nhất. Điều này đạt được thông qua khái niệm kết hợp trong SQL Server.

Cơ hội này thường cần thiết vì dữ liệu trong cơ sở dữ liệu quan hệ thường được chuẩn hóa. Ví dụ:chúng tôi có dữ liệu nhân viên trải rộng trên hai hoặc nhiều bảng. Bảng đầu tiên sẽ là dữ liệu khách hàng cơ bản và được gọi là nhân viên. Bảng thứ hai sẽ là bộ phận .

Sự nhất quán về dữ liệu yêu cầu mối quan hệ chính xác giữa khách hàng và bộ phận. Trả lại dữ liệu đầy đủ cho một nhóm nhân viên và các bộ phận của họ yêu cầu phải tham gia cả hai bảng.

Các phép toán nối SQL cũng có thể bao gồm nhiều hơn hai bảng.

Một trường hợp khác tồn tại các mối quan hệ Khóa ngoại như vậy giữa các bảng là để tóm tắt chi tiết bảng.

Những người đã làm việc với cơ sở dữ liệu mẫu AdventureWorks hoặc WideWorldImporters quen thuộc với Bán hàng.Orders và bảng Sales.OrderDetails. Trong trường hợp này, phần sau chứa thông tin chi tiết của từng đơn đặt hàng được ghi lại trong Đơn hàng bán hàng bàn. Hai bảng có mối quan hệ dựa trên thứ tự. Do đó, chúng ta có thể truy xuất dữ liệu từ cả hai bảng dưới dạng một tập kết quả duy nhất bằng cách sử dụng JOINS.

Các loại tham gia SQL Server

T-SQL cho phép các kiểu nối sau:

  1. Tham gia bên trong trả về tất cả các bản ghi chung cho tất cả các bảng có liên quan đến truy vấn.
  2. Tham gia bên trái (Bên ngoài) trả về tất cả các bản ghi từ bên trái bảng và tất cả các bản ghi từ bên phải bảng đó cũng xảy ra trong bảng bên trái. Các điều khoản còn lại đúng tham chiếu đến vị trí của bảng so với mệnh đề JOIN.
  3. Tham gia Bên phải (Bên ngoài) trả về tất cả các bản ghi từ bên phải bảng và tất cả các bản ghi từ bên trái bảng đó cũng xảy ra trong bảng bên trái. Các điều khoản tương tự như trường hợp trước.
  4. Tham gia Toàn bộ Bên ngoài trả về tất cả các bản ghi chung cho cả hai bảng, cộng với tất cả các bản ghi khác từ cả hai bảng. Các cột không có hàng tương ứng trong bảng khác trả về NULL
  5. Tham gia chéo , còn được gọi là Tham gia Descartes , trả về tích lũy thừa của dữ liệu từ cả hai bảng. Do đó, tập hợp kết quả cuối cùng cho mỗi hàng trong bảng A sẽ chứa ánh xạ của tất cả các hàng trong bảng B và ngược lại.

Bài viết này sẽ tập trung vào SQL INNER JOIN.

Bảng mẫu

Để chứng minh khái niệm liên kết bên trong, chúng tôi sử dụng ba bảng liên quan từ cơ sở dữ liệu TSQLV4 do Itzik Ben-Gan xây dựng.

Danh sách sau đây cho thấy cấu trúc của các bảng này.

-- Listing 1: Structure of the Sales.Customers Table

CREATE TABLE [Sales].[Customers](
	[custid] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
	[companyname] [nvarchar](40) NOT NULL,
	[contactname] [nvarchar](30) NOT NULL,
	[contacttitle] [nvarchar](30) NOT NULL,
	[address] [nvarchar](60) NOT NULL,
	[city] [nvarchar](15) NOT NULL,
	[region] [nvarchar](15) NULL,
	[postalcode] [nvarchar](10) NULL,
	[country] [nvarchar](15) NOT NULL,
	[phone] [nvarchar](24) NOT NULL,
	[fax] [nvarchar](24) NULL,
 CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
(
	[custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

Lưu ý mối quan hệ khóa ngoại giữa cột custid trong Sales.Orders và cột custid trong Sales.Customers .

Để thực hiện các JOIN, chúng ta phải chỉ định một cột chung như vậy làm cơ sở JOIN.

Nó không yêu cầu nghiêm ngặt mối quan hệ khóa ngoại để thực hiện truy vấn JOIN, nhưng các cột xác định tập kết quả phải có thể so sánh được.

Khóa ngoại cũng có thể giúp cải thiện các truy vấn JOIN, đặc biệt nếu cột khóa ngoại được lập chỉ mục.

-- Listing 2: Structure of the Sales.Orders Table

CREATE TABLE [Sales].[Orders](
	[orderid] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
	[custid] [int] NULL,
	[empid] [int] NOT NULL,
	[orderdate] [date] NOT NULL,
	[requireddate] [date] NOT NULL,
	[shippeddate] [date] NULL,
	[shipperid] [int] NOT NULL,
	[freight] [money] NOT NULL,
	[shipname] [nvarchar](40) NOT NULL,
	[shipaddress] [nvarchar](60) NOT NULL,
	[shipcity] [nvarchar](15) NOT NULL,
	[shipregion] [nvarchar](15) NULL,
	[shippostalcode] [nvarchar](10) NULL,
	[shipcountry] [nvarchar](15) NOT NULL,
 CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
	[orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [Sales].[Orders] ADD  CONSTRAINT [DFT_Orders_freight]  DEFAULT ((0)) FOR [freight]
GO
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([custid])
REFERENCES [Sales].[Customers] ([custid])
GO
ALTER TABLE [Sales].[Orders] CHECK CONSTRAINT [FK_Orders_Customers]
GO
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Employees] FOREIGN KEY([empid])
REFERENCES [HR].[Employees] ([empid])
GO
ALTER TABLE [Sales].[Orders] CHECK CONSTRAINT [FK_Orders_Employees]
GO
ALTER TABLE [Sales].[Orders]  WITH CHECK ADD  CONSTRAINT [FK_Orders_Shippers] FOREIGN KEY([shipperid])
REFERENCES [Sales].[Shippers] ([shipperid])
GO
ALTER TABLE [Sales].[Orders] CHECK CONSTRAINT [FK_Orders_Shippers]
GO
-- Listing 3: Structure of the Sales.OrderDetails Table

CREATE TABLE [Sales].[OrderDetails](
	[orderid] [int] NOT NULL,
	[productid] [int] NOT NULL,
	[unitprice] [money] NOT NULL,
	[qty] [smallint] NOT NULL,
	[discount] [numeric](4, 3) NOT NULL,
 CONSTRAINT [PK_OrderDetails] PRIMARY KEY CLUSTERED 
(
	[orderid] ASC,
	[productid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [Sales].[OrderDetails] ADD  CONSTRAINT [DFT_OrderDetails_unitprice]  DEFAULT ((0)) FOR [unitprice]
GO
ALTER TABLE [Sales].[OrderDetails] ADD  CONSTRAINT [DFT_OrderDetails_qty]  DEFAULT ((1)) FOR [qty]
GO
ALTER TABLE [Sales].[OrderDetails] ADD  CONSTRAINT [DFT_OrderDetails_discount]  DEFAULT ((0)) FOR [discount]
GO
ALTER TABLE [Sales].[OrderDetails]  WITH CHECK ADD  CONSTRAINT [FK_OrderDetails_Orders] FOREIGN KEY([orderid])
REFERENCES [Sales].[Orders] ([orderid])
GO
ALTER TABLE [Sales].[OrderDetails] CHECK CONSTRAINT [FK_OrderDetails_Orders]
GO
ALTER TABLE [Sales].[OrderDetails]  WITH CHECK ADD  CONSTRAINT [FK_OrderDetails_Products] FOREIGN KEY([productid])
REFERENCES [Production].[Products] ([productid])
GO
ALTER TABLE [Sales].[OrderDetails] CHECK CONSTRAINT [FK_OrderDetails_Products]
GO
ALTER TABLE [Sales].[OrderDetails]  WITH CHECK ADD  CONSTRAINT [CHK_discount] CHECK  (([discount]>=(0) AND [discount]<=(1)))
GO
ALTER TABLE [Sales].[OrderDetails] CHECK CONSTRAINT [CHK_discount]
GO
ALTER TABLE [Sales].[OrderDetails]  WITH CHECK ADD  CONSTRAINT [CHK_qty] CHECK  (([qty]>(0)))
GO
ALTER TABLE [Sales].[OrderDetails] CHECK CONSTRAINT [CHK_qty]
GO
ALTER TABLE [Sales].[OrderDetails]  WITH CHECK ADD  CONSTRAINT [CHK_unitprice] CHECK  (([unitprice]>=(0)))
GO
ALTER TABLE [Sales].[OrderDetails] CHECK CONSTRAINT [CHK_unitprice]
GO

Truy vấn Mẫu với SQL INNER JOIN

Hãy thực hiện một số truy vấn mẫu bằng SQL INNER JOIN.

Trong Liệt kê 4, chúng tôi thực thi một truy vấn tìm nạp TẤT CẢ các hàng chung cho bảng Sales.Customers và bảng Sales.Orders. Chúng tôi sử dụng cột custid làm điều kiện cho phép nối.

Lưu ý rằng mệnh đề ON là một bộ lọc rất giống mệnh đề WHERE. Chúng tôi cũng đã sử dụng bí danh để phân biệt các bảng.

-- Listing 4: Customer Orders

use TSQLV4
go
select * from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid;

Trong Liệt kê 5, chúng tôi thu hẹp truy vấn xuống các cột cụ thể cho Người bán hàng và bảng Bán hàng.Đơn hàng bàn. Chúng tôi sử dụng custid làm điều kiện cho sự tham gia.

Quan sát rằng mệnh đề ON là một bộ lọc rất giống mệnh đề WHERE. Chúng tôi cũng đã sử dụng bí danh để phân biệt các bảng.

-- Listing 5: Customer Orders with specific Rows
use TSQLV4
go
select
contactname
, contacttitle
, address
, orderid
, orderdate
, shipaddress
, shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid;

Trong Liệt kê 6, chúng tôi mở rộng suy nghĩ bằng cách giới thiệu mệnh đề WHERE để lọc dữ liệu cho một khách hàng. Chúng tôi cũng đã thêm các bí danh vào danh sách cột.

Mặc dù không cần thiết trong ví dụ này, nhưng có những trường hợp bạn cần chiếu các cột có cùng tên từ cả hai bảng. Sau đó, các cột sẽ cần một biểu thức dưới dạng tên gồm hai phần, sử dụng bí danh hoặc tên của bảng.

-- Listing 6: Customer Orders for a Single Customer
use TSQLV4
go
select 
sc.contactname
, sc.contacttitle
, sc.address
, so.orderid
, so.orderdate
, so.shipaddress
, so.shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid
where sc.contactname='Allen, Michael';

Trong danh sách 7, chúng tôi giới thiệu cột custid. Chúng tôi có thể phân biệt các cột bằng cách sử dụng bí danh, nhưng chúng tôi không thể phân biệt hai custid các cột trong đầu ra (Xem Hình 4). Chúng tôi có thể khắc phục điều này bằng cách sử dụng bí danh:

-- Listing 7: Customer Orders for a Single Customer with Common Column
use TSQLV4
go
select 
sc.custid
, sc.contactname
, sc.contacttitle
, sc.address
, so.custid
, so.orderid
, so.orderdate
, so.shipaddress
, so.shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid
where sc.contactname='Allen, Michael';
-- Listing 8: Customer Orders for a Single Customer with Aliased Column
use TSQLV4
go
select 
sc.custid customer_custid
, sc.contactname
, sc.contacttitle
, sc.address
, so.custid order_custid
, so.orderid
, so.orderdate
, so.shipaddress
, so.shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid
where sc.contactname='Allen, Michael';

Trong Liệt kê 9, chúng tôi thêm bảng Sales.OrderDetails vào hỗn hợp. Khi kết hợp nhiều hơn hai bảng, tập hợp kết quả từ hai bảng đầu tiên JOIN sẽ trở thành bên trái bảng cho bảng tiếp theo. Tuy nhiên, thứ tự của các bảng trong truy vấn JOIN không ảnh hưởng đến kết quả cuối cùng.

Lưu ý rằng chúng tôi sử dụng một thẻ đại diện để tìm nạp TẤT CẢ các cột từ bảng Sales.OrderDetails.

-- Listing 9: Inner Join with Three Tables

use TSQLV4
go
select 
sc.custid customer_custid
, sc.contactname
, sc.contacttitle
, sc.address
, so.custid order_custid
, so.orderid
, so.orderdate
, so.shipaddress
, so.shipcountry
, sod.*
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid
inner join Sales.OrderDetails sod
on so.orderid=sod.orderid
where sc.contactname='Allen, Michael';

Liệt kê 10 giới thiệu bảng Sản xuất. Sản phẩm hiển thị cho chúng ta chi tiết sản phẩm liên quan đến đơn đặt hàng.

-- Listing 10: Inner Join with Four Tables

use TSQLV4
go
select 
sc.custid customer_custid
, sc.contactname
, sc.contacttitle
, sc.address
, so.custid order_custid
, so.orderid
, so.orderdate
, so.shipaddress
, so.shipcountry
, sod.*
, pp.productname
, pp.unitprice
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid
inner join Sales.OrderDetails sod
on so.orderid=sod.orderid
inner join Production.Products pp
on sod.productid=pp.productid
where sc.contactname='Allen, Michael';

THAM GIA Không Trang bị

Vì mệnh đề ON là một bộ lọc, chúng ta có thể sử dụng các toán tử khác với toán tử “=”. Các JOIN thường hỗ trợ việc sử dụng các bất đẳng thức như <,>,! =, = trong mệnh đề ON. Liệt kê 11 chứng minh điều này.

Việc chạy các truy vấn này sẽ trả về các tập kết quả khác nhau.

-- Listing 11: Non-Equi JOINs, "Equal to"
use TSQLV4
go
select
contactname
, contacttitle
, address
, orderid
, orderdate
, shipaddress
, shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid=so.custid;
-- Listing 12: Non-Equi JOINs, "Not Equal to"
use TSQLV4
go
select
contactname
, contacttitle
, address
, orderid
, orderdate
, shipaddress
, shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid<>so.custid;
-- Listing 13: Non-Equi JOINs, "Less than OR Equal to"
use TSQLV4
go
select
contactname
, contacttitle
, address
, orderid
, orderdate
, shipaddress
, shipcountry
from Sales.Customers sc
inner join Sales.Orders so
on sc.custid<=so.custid;

Kết luận

Bài viết này đã thảo luận về các SQL INNER JOIN và trình bày các ví dụ về việc sử dụng nó. Nó bao gồm các tình huống có hai, ba và bốn bảng trong cùng một truy vấn.

Sử dụng các bảng có liên quan, chúng tôi cũng đã minh họa cách chúng tôi có thể thay đổi cấu trúc truy vấn để hiển thị kết quả đầu ra theo yêu cầu của chúng tôi. Chúng tôi cũng đã thêm các ví dụ ngắn gọn về các THAM GIA Không Trang bị.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kết nối với MS SQL Server bằng Xác thực Windows bằng Python?

  2. Làm cách nào để nhập tệp Excel vào SQL Server?

  3. Lỗi chuyển đổi dữ liệu tải hàng loạt (loại ký tự không khớp hoặc không hợp lệ cho mã hóa được chỉ định) cho hàng 1, cột 4 (Năm)

  4. Thoát khỏi báo giá đơn trong SQL Server

  5. Truy vấn SQL để lấy dữ liệu trong 3 tháng qua