Partition by trong sql

Đăng bởi Lưu Đại vào ngày 18-12-2022
Trước mình có 1 task yêu cầu phải join bảng A và B (A has_many B) nhưng chỉ join đúng duy nhất 1 bản ghi trong bảng với điều kiện nhất định. 
Lâu lâu không động vào hôm nay có bạn đồng nghiệp hỏi tại sao lại dùng hàm ABC mà mình quên khuấy mất. Nên quyết định lên đây note lại 

Vấn đề ( tự nghĩ ra =)) do ko được lộ spec dự án ). 

Bảng A quan hệ 1 - N với bảng B. Yêu cầu là phải lấy bản ghi B mới nhất, B mới nhì và B với trường x = 1 (tại 1 thời điểm chỉ có duy nhất 1 bản ghi B với x = 1). 

Partition by trong sql. 

Trước tiên là có thể giải quyết bài toán trên bằng cách load hết các bản ghi B của A ra và xử lý bằng vòng lặp. Nhưng hồi đó mình quyết định không làm vậy =))) Mà try hard bằng sql với hy vọng (không chắc chắn lắm) là performance sẽ tốt hơn. Thật sự hiện tại mình cũng k rõ performance có tốt hơn không? Sau một hồi research thì mình tìm ra hàm partition by trong sql: Partiton by sẽ gom các dữ liệu có cùng điều kiện vào một partition (như kiểu tạo ra một bảng con chứa những dữ liệu có điều kiện nhất định á). 

Row number trong sql. 

Cái tiếp theo mà mình tìm thấy khi dùng partition_by là hàm row_number() dùng để đánh số thứ tự cho 1 partition.
Sau đó để giải quyết trường hợp trên mình tạo partition bảng B r dùng row_number để đánh số lấy các bản ghi có row_number là 1 hoặc 2 tùy trường hợp để join lại với bảng A

Demo

SELECT A.*, B.* 
FROM A 
LEFT OUTER JOIN (
	SELECT *, ROW_NUMBER() OVER (PARTITION BY B.a_id ORDER_BY created_at DESC) AS row_num
	FROM B) AS numered_b 
	WHERE numered_b.row_num = 1 # hoặc bằng 2 nếu lấy bản ghi gần cuối
) AS last_b	ON A.id = last_b.a_id