Cách sử dụng Subquery trong MySQL

19/06/2023 - lượt xem
Chia sẻ
 
Rate this post

Trong bài viết này, chúng ta sẽ cùng học cách sử dụng subquery trong MySQL để viết các truy vấn phức tạp và giải thích khái niệm truy vấn con tương quan.

Giới thiệu về MySQL Subquery

MySQL Subquery là một truy vấn được lồng trong một truy vấn khác, chẳng hạn như  SELECT, hoặc  . Ngoài ra, một truy vấn con có thể được lồng trong một truy vấn con khác.INSERT UPDATE DELETE

MySQL Subquery được gọi là truy vấn bên trong trong khi truy vấn chứa truy vấn con đó được gọi là truy vấn bên ngoài. Truy vấn con có thể được sử dụng ở bất kỳ đâu mà biểu thức đó được sử dụng và phải được đóng trong ngoặc đơn.

Ví dụ: truy vấn sau đây sử dụng truy vấn con để trả về những nhân viên làm việc trong các văn phòng ở Hoa Kỳ.

SELECT 
    lastName, firstName
FROM
    employees
WHERE
    officeCode IN (SELECT 
            officeCode
        FROM
            offices
        WHERE
            country = 'USA');

Trong ví dụ này:

  • Truy vấn con trả về tất cả các mã văn phòng của các văn phòng đặt tại Hoa Kỳ.
  • Truy vấn bên ngoài chọn họ và tên của nhân viên làm việc trong văn phòng có mã văn phòng trong tập kết quả được trả về bởi truy vấn phụ.
Khi thực hiện truy vấn, MySQL đánh giá truy vấn con trước và sử dụng kết quả của truy vấn con cho truy vấn bên ngoài.

Sử dụng Subquery trong mệnh đề WHERE

Chúng tôi sẽ sử dụng bảng payments trong cơ sở dữ liệu mẫu để trình diễn.

Sử dụng Subquery với các toán tử so sánh

Bạn có thể sử dụng các toán tử so sánh, chẳng hạn như =, >, < để so sánh một giá trị đơn do truy vấn con trả về với biểu thức trong mệnh đề WHERE.

Ví dụ: truy vấn sau trả về khách hàng có khoản thanh toán cao nhất.

SELECT 
    customerNumber, 
    checkNumber, 
    amount
FROM
    payments
WHERE
    amount = (SELECT MAX(amount) FROM payments);

kết quả:

Bên cạnh toán tử =, bạn có thể sử dụng các toán tử so sánh khác như lớn hơn ( >), lớn hơn hoặc bằng (>=) nhỏ hơn ( <) và nhỏ hơn hoặc bằng (<=).

Ví dụ: bạn có thể tìm khách hàng có khoản thanh toán lớn hơn khoản thanh toán trung bình bằng cách sử dụng truy vấn phụ:

SELECT 
    customerNumber, 
    checkNumber, 
    amount
FROM
    payments
WHERE
    amount > (SELECT 
            AVG(amount)
        FROM
            payments);

kết quả:

Trong ví dụ này:

  • Đầu tiên, nhận khoản thanh toán trung bình bằng cách sử dụng truy vấn phụ.
  • Sau đó, chọn các khoản thanh toán lớn hơn khoản thanh toán trung bình do truy vấn con trả về trong truy vấn bên ngoài.

Sử dụng MySQL Subquert với toán tử IN và NOT IN

Nếu truy vấn con trả về nhiều hơn một giá trị, bạn có thể sử dụng các toán tử khác chẳng hạn như toán tử IN hoặc NOT IN trong mệnh đề WHERE.

Xem các bảng sau đây customers và orders:

Ví dụ: bạn có thể sử dụng truy vấn con với toán tử NOT IN để tìm những khách hàng chưa đặt bất kỳ đơn hàng nào như sau:

SELECT 
    customerName
FROM
    customers
WHERE
    customerNumber NOT IN (SELECT DISTINCT
            customerNumber
        FROM
            orders);

kết quả

Sử dụng Subquery trong mệnh đề FROM

Khi bạn sử dụng truy vấn phụ trong mệnh đề FROM, tập hợp kết quả trả về từ truy vấn phụ được dùng làm bảng tạm thời. Bảng này được gọi là bảng dẫn xuất hoặc truy vấn con cụ thể hóa.

Truy vấn con sau tìm số lượng mặt hàng tối đa , tối thiểu và trung bình trong đơn đặt hàng:

SELECT 
    MAX(items), 
    MIN(items), 
    FLOOR(AVG(items))
FROM
    (SELECT 
        orderNumber, COUNT(orderNumber) AS items
    FROM
        orderdetails
    GROUP BY orderNumber) AS lineitems;

kết quả

Lưu ý rằng FLOOR() được sử dụng để xóa các vị trí thập phân khỏi giá trị trung bình của các mục.

MySQL correlated subquery

Trong các ví dụ trước, bạn nhận thấy rằng truy vấn phụ là độc lập. Điều đó có nghĩa là bạn có thể thực thi truy vấn con dưới dạng truy vấn độc lập, ví dụ:

SELECT 
    orderNumber, 
    COUNT(orderNumber) AS items
FROM
    orderdetails
GROUP BY orderNumber;

Không giống như truy vấn con độc lập, truy vấn con tương quan là truy vấn con sử dụng dữ liệu từ truy vấn bên ngoài. Nói cách khác, truy vấn con tương quan phụ thuộc vào truy vấn bên ngoài. Truy vấn con tương quan được đánh giá một lần cho mỗi hàng trong truy vấn bên ngoài.

Xem bảng sau products từ cơ sở dữ liệu mẫu:

Ví dụ sau sử dụng truy vấn con tương quan để chọn các sản phẩm có giá mua lớn hơn giá mua trung bình của tất cả các sản phẩm trong mỗi  dòng sản phẩm.

SELECT 
    productname, 
    buyprice
FROM
    products p1
WHERE
    buyprice > (SELECT 
            AVG(buyprice)
        FROM
            products
        WHERE
            productline = p1.productline)

kết quả:

Trong ví dụ này, cả truy vấn bên ngoài và truy vấn con tương quan đều tham chiếu đến cùng một bảng products. Do đó, chúng ta cần sử dụng bí danh bảng p1 cho bảng products trong truy vấn bên ngoài.

Không giống như một truy vấn con thông thường, bạn không thể thực thi một truy vấn con tương quan một cách độc lập như thế này. Nếu bạn làm như vậy, MySQL không biết bảng p1 và sẽ báo lỗi.

SELECT 
    AVG(buyprice)
FROM
    products
WHERE
    productline = p1.productline;

Đối với mỗi hàng trong bảng products (hoặc p1), truy vấn con tương quan cần thực hiện một lần để có được giá mua trung bình của tất cả các sản phẩm trong hàng productline đó.

Nếu giá mua của hàng hiện tại lớn hơn giá mua trung bình do truy vấn con tương quan trả về, thì truy vấn sẽ bao gồm hàng đó trong tập hợp kết quả.

Sử dụng MySQL Subquert với EXISTSNOT EXISTS

Khi truy vấn con được sử dụng với  toán tử EXISTS hoặc NOT EXISTS, truy vấn con trả về giá trị Boolean của TRUE hoặc FALSE. Truy vấn sau đây minh họa một truy vấn con được sử dụng với toán tử EXISTS:

SELECT 
    *
FROM
    table_name
WHERE
    EXISTS( subquery );

Trong truy vấn ở trên, nếu truy vấn con trả về bất kỳ hàng nào thì EXISTS subquery trả về TRUE, nếu không thì trả về FALSE.

và thường được sử dụng trong các truy vấn con tương quan EXISTS.NOT EXISTS

Chúng ta hãy xem các bảng orders và orderdetails từ cơ sở dữ liệu mẫu :

Truy vấn sau tìm các đơn đặt hàng có tổng giá trị lớn hơn 60K.

SELECT 
    orderNumber, 
    SUM(priceEach * quantityOrdered) total
FROM
    orderdetails
        INNER JOIN
    orders USING (orderNumber)
GROUP BY orderNumber
HAVING SUM(priceEach * quantityOrdered) > 60000;

Nó trả về 3 hàng, nghĩa là có ba đơn đặt hàng có tổng giá trị lớn hơn 60K.

Bạn có thể sử dụng truy vấn ở trên làm truy vấn con tương quan để tìm những khách hàng đã đặt ít nhất một đơn đặt hàng có tổng giá trị lớn hơn 60K bằng cách sử dụng toán tử EXISTS:

SELECT 
    customerNumber, 
    customerName
FROM
    customers
WHERE
    EXISTS( SELECT 
            orderNumber, SUM(priceEach * quantityOrdered)
        FROM
            orderdetails
                INNER JOIN
            orders USING (orderNumber)
        WHERE
            customerNumber = customers.customerNumber
        GROUP BY orderNumber
        HAVING SUM(priceEach * quantityOrdered) > 60000);

Tổng kết

  • Subquery là một truy vấn được lồng trong một truy vấn khác (hoặc truy vấn bên ngoài).
  • Một truy vấn con tương quan phụ thuộc vào truy vấn bên ngoài.
  • Tham khảo thêm tại: https://www.mysqltutorial.org/mysql-subquery/

Các bài viết liên quan:

    Liên hệ với chúng tôi

    Để lại thông tin để nhận được các bài viết khác

    Rate this post

    Xem thêm nhiều bài tin mới nhất về Kiến thức

    Xem thêm