Câu trả lời:
Các exists
từ khóa có thể được sử dụng theo cách đó, nhưng thực sự nó dự định như là một cách để đếm tránh:
--this statement needs to check the entire table
select count(*) from [table] where ...
--this statement is true as soon as one match is found
exists ( select * from [table] where ... )
Điều này hữu ích nhất khi bạn có các if
câu lệnh có điều kiện, vì exists
có thể nhanh hơn rất nhiều count
.
Được in
sử dụng tốt nhất khi bạn có một danh sách tĩnh để vượt qua:
select * from [table]
where [field] in (1, 2, 3)
Khi bạn có một bảng trong một in
câu lệnh, việc sử dụng một bảng sẽ có ý nghĩa hơn join
, nhưng chủ yếu là không quan trọng. Trình tối ưu hóa truy vấn sẽ trả về cùng một kế hoạch. Trong một số triển khai (chủ yếu là cũ hơn, chẳng hạn như Microsoft SQL Server 2000), in
các truy vấn sẽ luôn có một kế hoạch tham gia lồng nhau , trong khi join
các truy vấn sẽ sử dụng lồng nhau, hợp nhất hoặc băm khi thích hợp. Các triển khai hiện đại hơn thông minh hơn và có thể điều chỉnh kế hoạch ngay cả khi in
được sử dụng.
select * from [table] where [field] in (select [field] from [table2])
trả về cùng kết quả (và gói truy vấn) như select * from [table] join [table2] on [table2].[field] = [table].[field]
.
table
, trong khi truy vấn thứ hai trả về mọi thứ từ table
và table2
. Trong một số cơ sở dữ liệu SQL (hầu hết cũ hơn), in
truy vấn sẽ được triển khai dưới dạng tham gia lồng nhau, trong khi join
truy vấn có thể được lồng, sáp nhập, băm, v.v. - bất cứ điều gì nhanh nhất.
exists
có thể được sử dụng trong một tuyên bố trường hợp, vì vậy chúng cũng có thể có ích theo cách đó, ví dụselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
EXISTS
sẽ cho bạn biết liệu một truy vấn có trả về bất kỳ kết quả nào không. ví dụ:
SELECT *
FROM Orders o
WHERE EXISTS (
SELECT *
FROM Products p
WHERE p.ProductNumber = o.ProductNumber)
IN
được sử dụng để so sánh một giá trị với nhiều giá trị và có thể sử dụng các giá trị bằng chữ, như thế này:
SELECT *
FROM Orders
WHERE ProductNumber IN (1, 10, 100)
Bạn cũng có thể sử dụng kết quả truy vấn với IN
mệnh đề, như sau:
SELECT *
FROM Orders
WHERE ProductNumber IN (
SELECT ProductNumber
FROM Products
WHERE ProductInventoryQuantity > 0)
Dựa trên trình tối ưu hóa quy tắc :
EXISTS
nhanh hơn nhiều so với IN
khi kết quả truy vấn phụ rất lớn.IN
nhanh hơn EXISTS
, khi kết quả truy vấn phụ rất nhỏ.Dựa trên tối ưu hóa chi phí :
Tôi giả sử bạn biết những gì họ làm và do đó được sử dụng khác nhau, vì vậy tôi sẽ hiểu câu hỏi của bạn là: Khi nào nên viết lại SQL để sử dụng IN thay vì EXISTS hoặc ngược lại.
Đó có phải là một giả định công bằng?
Chỉnh sửa : Lý do tôi hỏi là trong nhiều trường hợp, bạn có thể viết lại SQL dựa trên IN để sử dụng EXISTS thay vào đó và ngược lại, và đối với một số công cụ cơ sở dữ liệu, trình tối ưu hóa truy vấn sẽ xử lý hai cách khác nhau.
Ví dụ:
SELECT *
FROM Customers
WHERE EXISTS (
SELECT *
FROM Orders
WHERE Orders.CustomerID = Customers.ID
)
có thể được viết lại thành:
SELECT *
FROM Customers
WHERE ID IN (
SELECT CustomerID
FROM Orders
)
hoặc tham gia:
SELECT Customers.*
FROM Customers
INNER JOIN Orders ON Customers.ID = Orders.CustomerID
Vì vậy, câu hỏi của tôi vẫn là, người đăng ban đầu tự hỏi về những gì IN và EXISTS làm, và do đó làm thế nào để sử dụng nó, hoặc anh ta yêu cầu viết lại SQL bằng cách sử dụng IN để sử dụng EXISTS thay vào đó, hoặc ngược lại, sẽ là một ý tưởng tốt?
JOIN
, bạn sẽ cần mộtDISTINCT
EXISTS
nhanh hơn nhiều so với IN
khi kết quả truy vấn con rất lớn.
IN
nhanh hơn EXISTS
khi kết quả truy vấn con rất nhỏ.
CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO
INSERT INTO t1
SELECT 1, 'title 1', 5 UNION ALL
SELECT 2, 'title 2', 5 UNION ALL
SELECT 3, 'title 3', 5 UNION ALL
SELECT 4, 'title 4', 5 UNION ALL
SELECT null, 'title 5', 5 UNION ALL
SELECT null, 'title 6', 5
INSERT INTO t2
SELECT 1, 1, 'data 1' UNION ALL
SELECT 2, 1, 'data 2' UNION ALL
SELECT 3, 2, 'data 3' UNION ALL
SELECT 4, 3, 'data 4' UNION ALL
SELECT 5, 3, 'data 5' UNION ALL
SELECT 6, 3, 'data 6' UNION ALL
SELECT 7, 4, 'data 7' UNION ALL
SELECT 8, null, 'data 8' UNION ALL
SELECT 9, 6, 'data 9' UNION ALL
SELECT 10, 6, 'data 10' UNION ALL
SELECT 11, 8, 'data 11'
Truy vấn 1
SELECT
FROM t1
WHERE not EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
Truy vấn 2
SELECT t1.*
FROM t1
WHERE t1.id not in (SELECT t2.t1id FROM t2 )
Nếu trong t1
id của bạn có giá trị null thì Truy vấn 1 sẽ tìm thấy chúng, nhưng Truy vấn 2 không thể tìm thấy tham số null.
Tôi có nghĩa là IN
không thể so sánh bất cứ điều gì với null, vì vậy nó không có kết quả cho null, nhưng EXISTS
có thể so sánh mọi thứ với null.
Nếu bạn đang sử dụng IN
toán tử, công cụ SQL sẽ quét tất cả các bản ghi được tìm nạp từ truy vấn bên trong. Mặt khác, nếu chúng ta đang sử dụng EXISTS
, công cụ SQL sẽ dừng quá trình quét ngay khi tìm thấy kết quả khớp.
IN chỉ hỗ trợ các quan hệ bình đẳng (hoặc bất bình đẳng khi đi trước KHÔNG ).
Nó là từ đồng nghĩa với = any / = some , vd
select *
from t1
where x in (select x from t2)
;
EXISTS hỗ trợ các loại quan hệ biến thể, không thể biểu thị bằng IN , ví dụ -
select *
from t1
where exists (select null
from t2
where t2.x=t1.x
and t2.y>t1.y
and t2.z like '℅' || t1.z || '℅'
)
;
Sự khác biệt về hiệu suất và kỹ thuật giữa EXISTS và IN có thể xuất phát từ việc triển khai / giới hạn / lỗi cụ thể của nhà cung cấp, nhưng nhiều khi chúng không là gì ngoài những huyền thoại được tạo ra do thiếu hiểu biết về cơ sở dữ liệu bên trong.
Định nghĩa, độ chính xác của thống kê, cấu hình cơ sở dữ liệu và phiên bản của trình tối ưu hóa đều có tác động đến kế hoạch thực hiện và do đó đối với các số liệu hiệu suất.
Các Exists
từ khóa đánh giá đúng hay sai, nhưng IN
từ khóa so sánh tất cả giá trị trong cột truy vấn phụ tương ứng. Một số khác Select 1
có thể được sử dụng với Exists
lệnh. Thí dụ:
SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
Nhưng IN
kém hiệu quả nên Exists
nhanh hơn.
Tôi nghĩ,
EXISTS
là khi bạn cần khớp kết quả truy vấn với truy vấn con khác. Các kết quả truy vấn số 1 cần được truy xuất khi kết quả SubQuery khớp. Loại tham gia .. Ví dụ: chọn khách hàng bảng số 1 cũng đã đặt bảng đơn hàng số 2
IN là để truy xuất nếu giá trị của một cột cụ thể nằm trong IN
danh sách (1,2,3,4,5) Ví dụ: Chọn các khách hàng nằm trong các mã zip sau, tức là các giá trị zip_code nằm trong danh sách (....).
Khi nào nên sử dụng cái này hơn cái kia ... khi bạn cảm thấy nó đọc phù hợp (Giao tiếp có ý định tốt hơn).
Sự khác biệt nằm ở đây:
select *
from abcTable
where exists (select null)
Truy vấn trên sẽ trả về tất cả các bản ghi trong khi bên dưới sẽ trả về trống.
select *
from abcTable
where abcTable_ID in (select null)
Hãy thử và quan sát đầu ra.
Cái nào nhanh hơn phụ thuộc vào số lượng truy vấn được tìm nạp bởi truy vấn bên trong:
EXIST đánh giá đúng hay sai nhưng IN so sánh nhiều giá trị. Khi bạn không biết bản ghi có tồn tại hay không, bạn nên chọn EXIST
Lý do là vì toán tử EXISTS hoạt động dựa trên nguyên tắc ít nhất là tìm thấy. Nó trả về true và dừng bảng quét một lần ít nhất một hàng khớp.
Mặt khác, khi toán tử IN được kết hợp với truy vấn con, MySQL phải xử lý truy vấn con trước, sau đó sử dụng kết quả của truy vấn con để xử lý toàn bộ truy vấn.
Nguyên tắc chung là nếu truy vấn con chứa một khối lượng dữ liệu lớn, toán tử EXISTS cung cấp hiệu suất tốt hơn.
Tuy nhiên, truy vấn sử dụng toán tử IN sẽ thực hiện nhanh hơn nếu tập kết quả được trả về từ truy vấn con là rất nhỏ.
Tôi hiểu là cả hai nên giống nhau miễn là chúng ta không xử lý các giá trị NULL.
Lý do tương tự tại sao truy vấn không trả về giá trị cho = NULL vs là NULL. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
Đối với đối số boolean và so sánh đi, để tạo ra một boolean cả hai giá trị cần phải được so sánh và đó là cách bất kỳ nếu điều kiện hoạt động. Vì vậy, tôi không hiểu cách IN và EXISTS hành xử khác nhau.
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
https://docs.oracle.com/cd/B19306_01/server.102/b14211/sql_1016.htmlm#i28403
Nếu truy vấn con trả về nhiều hơn một giá trị, bạn có thể cần thực hiện truy vấn bên ngoài - nếu các giá trị trong cột được chỉ định trong điều kiện khớp với bất kỳ giá trị nào trong tập kết quả của truy vấn phụ. Để thực hiện nhiệm vụ này, bạn cần sử dụng in
từ khóa.
Bạn có thể sử dụng truy vấn con để kiểm tra xem có tồn tại một tập hợp các bản ghi không. Đối với điều này, bạn cần sử dụng exists
mệnh đề với một truy vấn con. Các exists
từ khóa luôn trả về giá trị đúng hoặc sai.
Tôi tin rằng điều này có một câu trả lời đơn giản. Tại sao bạn không kiểm tra nó từ những người đã phát triển chức năng đó trong hệ thống của họ?
Nếu bạn là nhà phát triển MS SQL, đây là câu trả lời trực tiếp từ Microsoft.
IN
:
Xác định xem một giá trị được chỉ định phù hợp với bất kỳ giá trị nào trong truy vấn con hoặc danh sách.
Chỉ định truy vấn con để kiểm tra sự tồn tại của các hàng.
Tôi thấy rằng việc sử dụng từ khóa EXISTS thường rất chậm (điều đó rất đúng trong Microsoft Access). Thay vào đó, tôi sử dụng toán tử nối theo cách này: nên-i-use-the-keyword-tồn tại-in-sql
EXISTS có hiệu suất nhanh hơn IN. Nếu Hầu hết các tiêu chí bộ lọc nằm trong truy vấn phụ thì tốt hơn nên sử dụng IN và Nếu hầu hết các tiêu chí bộ lọc nằm trong truy vấn chính thì tốt hơn nên sử dụng EXISTS.
Nếu bạn đang sử dụng toán tử IN, công cụ SQL sẽ quét tất cả các bản ghi được tìm nạp từ truy vấn bên trong. Mặt khác, nếu chúng ta đang sử dụng EXISTS, công cụ SQL sẽ dừng quá trình quét ngay khi tìm thấy kết quả khớp.
IN
và EXISTS
có thể tương đương và biến đổi lẫn nhau.
JOIN
thay thế choIN
.