Nếu các truy vấn cần kết hợp đều rất khác nhau, bạn có thể gặp phải một tình huống là trường đầu ra phải kết hợp dữ liệu của các loại dữ liệu khác nhau. Nếu vậy, truy vấn hợp hầu như thường sẽ trả về kết quả dưới dạng loại dữ liệu văn bản do loại dữ liệu có thể lưu giữ cả văn bản và số.
Để tìm hiểu cách truy vấn này hoạt động, chúng ta sẽ sử dụng truy vấn hợp Giao dịch sản phẩm trong cơ sở dữ liệu mẫu Northwind. Mở cơ sở dữ liệu mẫu đó, rồi mở truy vấn Giao dịch sản phẩm ở dạng xem biểu dữ liệu. Mười bản ghi cuối cùng phải tương tự như đầu ra này:
ID Sản phẩm | Ngày đặt hàng | Tên công ty | Giao dịch | Số lượng |
77 | 22/01/2006 | Nhà cung cấp B | Mua | 60 |
80 | 22/01/2006 | Nhà cung cấp D | Mua | 75 |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 125 |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 200 |
7 | 20/01/2006 | Công ty D | Bán | 10 |
51 | 20/01/2006 | Công ty D | Bán | 10 |
80 | 20/01/2006 | Công ty D | Bán | 10 |
34 | 15/01/2006 | Công ty AA | Bán | 100 |
80 | 15/01/2006 | Công ty AA | Bán | 25 |
Hãy giả định rằng bạn muốn trường Số lượng chia tách vào hai - Mua và Bán. Cũng hãy giả định rằng bạn muốn có giá trị số không cố định cho trường không có giá trị. Đây là giao diện của SQL đối với truy vấn hợp này:
SELECT [Product ID], [Order Date], [Company Name], [Transaction], 0 As Buy, [Quantity] As Sell FROM [Product Orders] UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity] As Buy, 0 As Sell FROM [Product Purchases] ORDER BY [Order Date] DESC;Nếu bạn chuyển đổi sang dạng xem biểu dữ liệu, bạn sẽ thấy mười bản ghi cuối cùng giờ đây được hiển thị giống như sau:
ID Sản phẩm | Ngày đặt hàng | Tên công ty | Giao dịch | Mua | Bán |
74 | 22/01/2006 | Nhà cung cấp B | Mua | 31 | 0 |
77 | 22/01/2006 | Nhà cung cấp B | Mua | 60 | 0 |
80 | 22/01/2006 | Nhà cung cấp D | Mua | 75 | 0 |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 125 | 0 |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 200 | 0 |
7 | 20/01/2006 | Công ty D | Bán | 0 | 10 |
51 | 20/01/2006 | Công ty D | Bán | 0 | 10 |
80 | 20/01/2006 | Công ty D | Bán | 0 | 10 |
34 | 15/01/2006 | Công ty AA | Bán | 0 | 100 |
80 | 15/01/2006 | Công ty AA | Bán | 0 | 25 |
Tiếp tục ví dụ này, điều gì sẽ xảy ra nếu bạn muốn các trường có số không là trống? Bạn có thể sửa đổi SQL để không hiển thị gì thay vì số không bằng cách thêm từ khóa Null giống như sau:
SELECT [Product ID], [Order Date], [Company Name], [Transaction], Null As Buy, [Quantity] As Sell FROM [Product Orders] UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity] As Buy, Null As Sell FROM [Product Purchases] ORDER BY [Order Date] DESC;Tuy nhiên, khi bạn có thể quan sát việc chuyển đổi sang dạng xem biểu dữ liệu, lúc này bạn đã có một kết quả không mong muốn. Trong cột Mua, mỗi trường đều bị xóa:
ID Sản phẩm | Ngày đặt hàng | Tên công ty | Giao dịch | Mua | Bán |
74 | 22/01/2006 | Nhà cung cấp B | Mua | ||
77 | 22/01/2006 | Nhà cung cấp B | Mua | ||
80 | 22/01/2006 | Nhà cung cấp D | Mua | ||
81 | 22/01/2006 | Nhà cung cấp A | Mua | ||
81 | 22/01/2006 | Nhà cung cấp A | Mua | ||
7 | 20/01/2006 | Công ty D | Bán | 10 | |
51 | 20/01/2006 | Công ty D | Bán | 10 | |
80 | 20/01/2006 | Công ty D | Bán | 10 | |
34 | 15/01/2006 | Công ty AA | Bán | 100 | |
80 | 15/01/2006 | Công ty AA | Bán | 25 |
Lý do mà điều này xảy ra là vì Access xác định loại dữ liệu của các trường từ truy vấn đầu tiên. Trong ví dụ này, Null không phải là một số.
Vì vậy, điều gì xảy ra nếu bạn tìm cách và chèn một chuỗi trống cho giá trị của các trường trống? SQL đối với nỗ lực này có thể có dạng như sau:
SELECT [Product ID], [Order Date], [Company Name], [Transaction], "" As Buy, [Quantity] As Sell FROM [Product Orders] UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity] As Buy, "" As Sell FROM [Product Purchases] ORDER BY [Order Date] DESC;Khi bạn chuyển đổi sang dạng xem biểu dữ liệu, bạn sẽ thấy rằng Access truy xuất các giá trị Mua nhưng đã chuyển đổi các giá trị này thành văn bản. Bạn có thể biết đây là giá trị văn bản vì được căn trái ở dạng xem biểu dữ liệu. Chuỗi trống trong truy vấn đầu tiên không phải là số là vì bạn thấy các kết quả này. Bạn cũng sẽ nhận thấy rằng các giá trị Bán cũng được chuyển đổi thành văn bản vì các bản ghi mua có chứa chuỗi trống.
ID Sản phẩm | Ngày đặt hàng | Tên công ty | Giao dịch | Mua | Bán |
74 | 22/01/2006 | Nhà cung cấp B | Mua | 31 | |
77 | 22/01/2006 | Nhà cung cấp B | Mua | 60 | |
80 | 22/01/2006 | Nhà cung cấp D | Mua | 75 | |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 125 | |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 200 | |
7 | 20/01/2006 | Công ty D | Bán | 10 | |
51 | 20/01/2006 | Công ty D | Bán | 10 | |
80 | 20/01/2006 | Công ty D | Bán | 10 | |
34 | 15/01/2006 | Công ty AA | Bán | 100 | |
80 | 15/01/2006 | Công ty AA | Bán | 25 |
Vật thì bạn giải quyết vấn đề này như thế nào?
Giải pháp là buộc truy vấn có giá trị trường là một số. Điều đó có thể được thực hiện bằng biểu thức:
IIf(False, 0, Null)Điều kiện để kiểm tra, False, sẽ không bao giờ là True, do đó biểu thức sẽ luôn trả về Null nhưng Access vẫn đánh giá cả hai tùy chọn đầu ra và quyết định đầu ra là số hoặc Null.
Đây là cách chúng ta có thể sử dụng biểu thức này trong ví dụ hoạt động của mình:
SELECT [Product ID], [Order Date], [Company Name], [Transaction], IIf(False, 0, Null) As Buy, [Quantity] As Sell FROM [Product Orders] UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity] As Buy, Null As Sell FROM [Product Purchases] ORDER BY [Order Date] DESC;Lưu ý rằng không cần thiết sửa đổi truy vấn thứ hai.
Nếu bạn chuyển đổi sang dạng xem biểu dữ liệu, lúc này bạn sẽ thấy kết quả mà chúng ta mong muốn:
ID Sản phẩm | Ngày đặt hàng | Tên công ty | Giao dịch | Mua | Bán |
74 | 22/01/2006 | Nhà cung cấp B | Mua | 31 | |
77 | 22/01/2006 | Nhà cung cấp B | Mua | 60 | |
80 | 22/01/2006 | Nhà cung cấp D | Mua | 75 | |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 125 | |
81 | 22/01/2006 | Nhà cung cấp A | Mua | 200 | |
7 | 20/01/2006 | Công ty D | Bán | 10 | |
51 | 20/01/2006 | Công ty D | Bán | 10 | |
80 | 20/01/2006 | Công ty D | Bán | 10 | |
34 | 15/01/2006 | Công ty AA | Bán | 100 | |
80 | 15/01/2006 | Công ty AA | Bán | 25 |
Phương pháp thay thế để đạt được cùng một kết quả là thêm các truy vấn trong truy vấn hợp với một truy vấn khác:
SELECT 0 As [Product ID], Date() As [Order Date], "" As [Company Name], "" As [Transaction], 0 As Buy, 0 As Sell FROM [Product Orders] WHERE FalseĐối với từng trường, Access trả về các giá trị cố định của loại dữ liệu bạn xác định. Tất nhiên, bạn không muốn đầu ra của truy vấn này gây cản trở đến kết quả, do đó bí kíp để tránh điều này là thêm vào mệnh đề WHERE thành False:
WHERE FalseĐây là một bí kíp nhỏ vì kết quả luôn là false và sau đó truy vấn không trả về bất kỳ giá trị nào. Kết hợp câu lệnh này với SQL hiện có và chúng ta có được câu lệnh được hoàn thành như sau:
SELECT 0 As [Product ID], Date() As [Order Date], "" As [Company Name], "" As [Transaction], 0 As Buy, 0 As Sell FROM [Product Orders] WHERE False UNION SELECT [Product ID], [Order Date], [Company Name], [Transaction], Null As Buy, [Quantity] As Sell FROM [Product Orders] UNION SELECT [Product ID], [Creation Date], [Company Name], [Transaction], [Quantity] As Buy, Null As Sell FROM [Product Purchases] ORDER BY [Order Date] DESC;
Lưu ý: Truy vấn đã kết hợp ở đây trong ví dụ này sử dụng cơ sở dữ liệu Northwind trả về 100 bản ghi, trong khi hai truy vấn riêng lẻ trả về 58 và 43 bản ghi có tổng cộng là 101 bản ghi. Nguyên nhân về sự không thống nhất này là vì hai bản ghi không phải là duy nhất. Hãy xem mục, Làm việc với các bản ghi riêng biệt trong truy vấn hợp bằng UNION ALL, để tìm hiểu cách để giải quyết kịch bản này bằng cách sử dụng UNION ALL.