Toán tử NOT EXISTS trong MySQL

Toán tử NOT EXISTS trong MySQL
Toán tử NOT EXISTS trong MySQL

Chức năng của Toán tử NOT EXISTS trong MySQL

Toán tử NOT EXISTS trong MySQL dùng để lấy danh sách thuộc khóa chính ở bảng này nhưng không nằm trong bảng khác hoặc có nằm trong bảng khác nhưng không thuộc điều kiện đưa ra.

Code Toán tử NOT EXISTS trong MySQL

Toán tử NOT EXISTS chưa có điều kiện trong MySQL

Ở ví dụ này mình kiểm tra những khách hàng chưa từng mua hàng:

select ten,id from tb_khachhang where NOT EXISTS (select * from tb_donhang where tb_donhang.idkhachhang= tb_khachhang.id);
<?php
   $dbhost = 'localhost';
   $dbuser = 'webmoi_userdata'; // Tên username
   $dbpass = 'IhNRcn9n'; // Mật khẩu
   // Kết nối đến tên username
   $conn = mysql_connect($dbhost, $dbuser, $dbpass);
   if(! $conn ){
     die('Không kết nối được: ' . mysql_error());
   }
   // Truy vấn bảng
   $sql = "select ten,id from tb_khachhang where NOT EXISTS (select * from tb_donhang where tb_donhang.idkhachhang= tb_khachhang.id)";
   // Chọn tên database
   mysql_select_db('webmoi_tendata');
   // Xét kiểu tiếng việt 
   mysql_query('SET NAMES "utf8"');
   // Kết quả truy vấn trả về mảng
   $ketqua = mysql_query($sql,$conn);
   if(!$ketqua){
	  die('Không thể lấy dữ liệu: ' . mysql_error());  
   }
   // Dùng vòng lặp để lấy ra từng hàng trong bảng	
   while($row = mysql_fetch_array($ketqua, MYSQL_ASSOC)){
		 echo "ID: {$row['id']} <br> ".
		 "Tên: {$row['ten']} <br> ".
         "--------------------------------<br>";
   }		 
   // Đóng kết nối database
   mysql_close($conn);
?>

Kết quả:

ID: 3
Tên: Trần Ngọc Thanh
--------------------------------

Toán tử NOT EXISTS có điều kiện trong MySQL

Ở ví dụ này mình kiểm tra những khách hàng chưa từng mua hàng hoặc có mua hàng nhưng không thuộc điều kiện đưa ra:

select ten,id from tb_khachhang where NOT EXISTS (select * from tb_donhang where tb_donhang.idkhachhang= tb_khachhang.id and idkhachhang>1);
<?php
   $dbhost = 'localhost';
   $dbuser = 'webmoi_userdata'; // Tên username
   $dbpass = 'IhNRcn9n'; // Mật khẩu
   // Kết nối đến tên username
   $conn = mysql_connect($dbhost, $dbuser, $dbpass);
   if(! $conn ){
     die('Không kết nối được: ' . mysql_error());
   }
   // Truy vấn bảng
   $sql = "select ten,id from tb_khachhang where NOT EXISTS (select * from tb_donhang where tb_donhang.idkhachhang= tb_khachhang.id and idkhachhang>1)";
   // Chọn tên database
   mysql_select_db('webmoi_tendata');
   // Xét kiểu tiếng việt 
   mysql_query('SET NAMES "utf8"');
   // Kết quả truy vấn trả về mảng
   $ketqua = mysql_query($sql,$conn);
   if(!$ketqua){
	  die('Không thể lấy dữ liệu: ' . mysql_error());  
   }
   // Dùng vòng lặp để lấy ra từng hàng trong bảng	
   while($row = mysql_fetch_array($ketqua, MYSQL_ASSOC)){
		 echo "ID: {$row['id']} <br> ".
		 "Tên: {$row['ten']} <br> ".
         "--------------------------------<br>";
   }		 
   // Đóng kết nối database
   mysql_close($conn);
?>

Kết quả:

ID: 1
Tên: Bùi Đan Trúc Quỳnh
--------------------------------
ID: 3
Tên: Trần Ngọc Thanh
--------------------------------

Khi nào nên sử dụng NOT EXISTS trong MySQL?

NOT EXISTS phù hợp khi cần kiểm tra một truy vấn con không trả về bất kỳ bản ghi nào thỏa điều kiện. Trong thực tế, toán tử này thường được dùng để tìm những dữ liệu chưa có bản ghi liên quan, xác nhận một điều kiện chưa xảy ra hoặc loại bỏ các bản ghi đã xuất hiện trong một tập dữ liệu khác.

Điểm đáng chú ý là NOT EXISTS tập trung vào việc kiểm tra có tồn tại bản ghi phù hợp hay không, thay vì lấy dữ liệu từ truy vấn con. Vì vậy, cách viết này thường khá trực quan khi xử lý các quan hệ giữa hai bảng.

Tìm dữ liệu chưa từng phát sinh bản ghi liên quan

Một tình huống phổ biến là tìm những đối tượng chưa có dữ liệu liên quan. Chẳng hạn, cần lấy danh sách khách hàng chưa từng đặt đơn hàng. Khi đó, bảng khách hàng là dữ liệu chính, còn NOT EXISTS được dùng để kiểm tra xem khách hàng đó có đơn hàng tương ứng hay chưa.

SELECT c.id, c.name
FROM customers AS c
WHERE NOT EXISTS (
    SELECT 1
    FROM orders AS o
    WHERE o.customer_id = c.id
);

Truy vấn trên chỉ giữ lại những khách hàng mà truy vấn con không tìm thấy đơn hàng có customer_id tương ứng. Cách này đặc biệt dễ hiểu khi yêu cầu nghiệp vụ được diễn đạt theo dạng “chỉ lấy những bản ghi không có dữ liệu liên quan”.

Kiểm tra điều kiện không tồn tại trước khi xử lý dữ liệu

NOT EXISTS cũng hữu ích khi cần kiểm tra một điều kiện trước khi thực hiện thao tác trên dữ liệu. Ví dụ, có thể xác định những sản phẩm chưa từng được ghi nhận trong bảng chi tiết đơn hàng để tìm các sản phẩm chưa phát sinh giao dịch.

SELECT p.id, p.product_name
FROM products AS p
WHERE NOT EXISTS (
    SELECT 1
    FROM order_items AS oi
    WHERE oi.product_id = p.id
);

Kiểu truy vấn này giúp thể hiện rõ mối quan hệ cần kiểm tra: sản phẩm được chọn khi không tồn tại bản ghi tương ứng trong bảng order_items. Khi đưa vào hệ thống thực tế, điều kiện bên trong truy vấn con nên bám sát khóa liên kết giữa các bảng để tránh kiểm tra sai phạm vi dữ liệu.

Kết hợp NOT EXISTS với nhiều điều kiện lọc

Điều kiện trong NOT EXISTS có thể kết hợp với nhiều tiêu chí khác nhau. Điều này phù hợp khi không chỉ cần kiểm tra bản ghi liên quan mà còn phải xác định bản ghi đó có thỏa một trạng thái, khoảng thời gian hoặc điều kiện nghiệp vụ cụ thể hay không.

SELECT c.id, c.name
FROM customers AS c
WHERE NOT EXISTS (
    SELECT 1
    FROM orders AS o
    WHERE o.customer_id = c.id
      AND o.status = 'completed'
);

Trong ví dụ này, khách hàng chỉ bị loại khỏi kết quả khi đã có ít nhất một đơn hàng ở trạng thái completed. Nếu khách hàng có đơn hàng nhưng chưa có đơn hoàn tất, họ vẫn có thể xuất hiện trong kết quả.

Khi thêm nhiều điều kiện, cần xác định chính xác ý nghĩa nghiệp vụ. Việc đặt điều kiện trong truy vấn con hay truy vấn chính có thể làm thay đổi kết quả, đặc biệt khi dữ liệu giữa hai bảng có nhiều trạng thái hoặc nhiều loại bản ghi.

Những trường hợp nên cân nhắc thay NOT EXISTS bằng cách khác

NOT EXISTS rất phù hợp với bài toán kiểm tra sự tồn tại, nhưng không phải lúc nào cũng là lựa chọn duy nhất. Với một số truy vấn đơn giản, LEFT JOIN kết hợp kiểm tra giá trị NULL có thể giúp câu lệnh dễ đọc hơn, đặc biệt khi cần lấy thêm dữ liệu từ bảng liên quan.

Ngoài ra, khi mục tiêu là lấy dữ liệu từ hai bảng thay vì chỉ kiểm tra sự tồn tại, JOIN có thể phù hợp hơn. Ngược lại, nếu chỉ cần trả lời câu hỏi “có bản ghi phù hợp hay không”, NOT EXISTS thường thể hiện đúng ý định của truy vấn và tránh phải lấy các cột không cần thiết từ truy vấn con.

Hiệu năng thực tế còn phụ thuộc vào cấu trúc bảng, số lượng dữ liệu, điều kiện truy vấn và chỉ mục. Với các truy vấn lớn, nên kiểm tra kế hoạch thực thi và bảo đảm các cột dùng để liên kết hoặc lọc có chỉ mục phù hợp thay vì lựa chọn toán tử chỉ dựa trên hình thức câu lệnh.

Lời kết

Cảm ơn các bạn đã tham khảo bài viết Toán tử NOT EXISTS trong MySQL.

Tải file database .sql về nếu muốn kiểm tra hoặc thực hành Tải về.

  • 0 Bình luận
CEO Bùi Tấn Lực | Founder Web Mới
Bùi Tấn Lực
Tìm hiểu về CEO Bùi Tấn Lực, Founder Web Mới với nhiều năm kinh nghiệm trong lĩnh vực phát triển website, SEO và chia sẻ kiến thức công nghệ
Chia sẻ nội dung đánh giá của bạn về Toán tử NOT EXISTS trong MySQL
Email, Điện thoại của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *
Đánh giá của bạn
Tên *
Email
Số điện thoại *
Bình luận, Hỏi đáp
Đăng ký tư vấn thiết kế website
Tìm hiểu 1 năm không bằng lắng nghe 1 câu tư vấn