JOINS và những điều cần biết trong cơ sở dữ liệu

1848

Lần đầu tiên nghe đến JOIN, mình đã nghĩ nó là cái gì đó cao siêu và hoành tráng lắm. Nhưng sau một hồi đọc rồi hiểu các kiểu về JOIN, thì mới nhận ra rằng nó chính là những truy vấn dữ liệu mà mình vẫn hay làm thường ngày, nhưng chỉ có điều là nó làm ngắn gọn và tăng tốc độ truy vấn lên thôi. “Chỉ có điều” ư? Không đâu! Làm ngắn gọn và tăng tốc độ truy vấn là giải quyết được một vấn đề khá to lớn đấy.

Join là gì?

Là một mệnh đề trong SQL, sử dụng để kết nối dữ liệu từ hai hay nhiều bảng trong cơ sở dữ liệu lại với nhau. Khi bạn cần truy vấn các cột dữ liệu từ nhiều bảng khác nhau để trả về trong cùng một tập kết quả, bạn cần dùng JOIN, SQL sẽ tạo ra một bảng tạm thời chứa dữ liệu kết quả từ JOIN.

Vai trò của join?

Ta xét ví dụ sau: Một mối quan hệ rất đơn giản giữa các thực thể trong một dự án Ruby on Rails:

 

 

Bây giờ, điều gì sẽ xảy ra khi cố gắng để có được user cho mỗi book?

 

Hãy nhìn vào console để xem điều gì xảy ra:

 

Dễ dàng thấy ra đây là vấn đề của N + 1 query. Truy vấn ban đầu của chúng ta (1 trong N +1) trả về collection có kích thước N, và đến lượt nó chạy một truy vấn cho mỗi một trong số chúng trong database (N trong N + 1).

Với việc sử dụng joins:

 

và console:

 

Vậy là joins trong trường hợp này đã giải quyết được vấn đề N+1 query. Đó mới chỉ là một trường hợp đơn giản ở trong Rails, ngoài ra join còn có giúp ích cho chúng ta rất nhiều nữa trong các truy vấn dữ liệu. Trước tiên, ta cần phải biết có những loại join nào.

Các kiểu join trong SQL?

Tùy vào các tình huống khác nhau với các yêu cầu về dữ liệu khác nhau, mà ta sẽ dùng các kiểu join khác nhau. Không có sự khác biệt nhiều giữa chúng, và cũng khá dễ hiểu, cơ bản có các loại như sau:

  1. INNER JOIN – trả về hàng khi có một sự phù hợp trong tất cả các bảng được join. 

Ví dụ 1: Lấy ra những Orders của Customers, ta INNER JOIN 2 bảng Orders và Customers như sau:

 

Trong đó bảng Orders là bảng trái vì bên trái từ khóa INNER JOIN, Customers là bảng phải. Biểu thức sau từ khóa ON cụ thể Orders.CustomerID = Customers.CustomerID là biểu thức khớp nối.

Ví dụ 2: Lấy ra các đơn hàng kèm theo tên khách hàng và tên người ship đơn hàng đó, ta INNER JOIN ba bảng Orders, Customers, Shippers:

  1. LEFT JOIN
  • LEFT JOIN trả về tất cả bản ghi bảng bên trái, ngay cả khi không có sự phù hợp trong bảng bên phải, còn những bản ghi nào của bảng bên phải phù hợp với bảng trái thì dữ liệu bản ghi đó được dùng để kết hợp với bản ghi bảng trái, nếu không có dữ liệu sẽ NULL. 

 

  1. RIGHT JOIN – trả về tất cả các hàng từ bảng bên phải, ngay cả khi không có sự phù hợp nào ở bảng bên trái.
  • Trường hợp này hoạt động giống với LEFT JOIN theo chiều ngược lại.
  1. FULL JOIN – trả về hàng khi có một sự phù hợp trong một trong các bảng.
  • Xét tất cả các kết quả, với SQLite không hỗ trợ (có thể thay thế bằng LEFT JOIN kết hợp với UNION)

 

  1. SELF JOIN – được sử dụng để tham gia một bảng với chính nó như thể bảng đó là hai bảng, tạm thời đổi tên ít nhất một bảng trong câu lệnh SQL.

Nếu muốn đọc để hiểu rõ hơn, các bạn có thể qua đọc series các bài viết về join sql trên w3chool: https://www.w3schools.com/sql/sql_join.asp

Ví dụ về join trong Rails app

  1. Ví dụ join 2 bảng

  1. Ví dụ join nhiều bảng cùng lúc

  1. Ví dụ lấy ra những User cùng với bookmarks post của user đó:

preload, eager_load, và includes trong Rails

Trong framework Ruby on Rails cung cấp những method query preload, eager_load, includes, references, joins, mỗi một phương pháp có cách hoạt động phù hợp với từng mục đích khác nhau. Việc không nắm rõ cách thức hoạt động, ưu điểm, nhược điểm của những method đó sẽ dẫn đến việc sử dụng sai lầm, tốn tài nguyên cũng như vấn đề performance của ứng dụng. Để hiểu rõ hơn các method trên và để biết được cách thức hoạt động và tốc độ xử lý của chúng, các bạn hãy tham khảo bảo viết: Tìm hiểu preload, eager_load, includes, references, and joins in Rails

Còn với vấn để mình đưa ra ở ví dụ đầu, khi sử dụng với preload, eager_load và includes thì nó sẽ như thế này đây:

  1. preload

  1. eager_load

  1. includes

 

TopDev via Viblo

SHARE