Đừng chỉ dừng hành trình SQL của bạn với JOIN.
Các cấp độ của SQL
Về cấp độ, mình chia kiến thức SQL được chia ra làm 6 giai đoạn.
Very Basic: gồm các lệnh select, from, where
Basic: gồm các lệnh group by và having
Beginners: lệnh join, left/right/outer/inner/self join.
Intermediate: Subqueries.
(Hầu hết mọi người dừng ở giai đoạn 4- intermediate 🤣🤣🤣. Giai đoạn 5 có thể giúp bạn cải thiện đáng kể khả năng viết những câu truy vấn phức tạp (complex queries). Điều này xảy ra do 95% các trường hợp, nó đủ với một backend CRUD cơ bản. Hôm nay ta sẽ vượt qua khoảng cách từ 4 đến 5, tức là từ Intermediate tới Advanced.)
- Advanced: Làm việc với CTEs (Common Table Expressions), window functions, lệnh partition by.
Nội dung ở cấp độ ‘Pro’ cũng rất hayß và hữu ích.
- Pro
- Đọc một chiến lược thực thi.
- Cách indexes hoạt động (Không chỉ là việc CREATE INDEX trên mỗi cột).
- Một hiểu biết sâu rộng về cách DB hoạt động.
Tại sao ta cần biết SQL?
Viết truy vấn SQL là một trong những công cụ tuyệt vời, hữu ích nhất mà một manager cần có, vì 3 lý do chính sau:
- Bạn có thể trả lời câu hỏi kinh doanh. Kĩ năng này vô cùng giá trị cho sự gắn kết giữa bạn với những người từ phía thương mại.
- Hầu hết các thiết kế kỹ thuật bắt đầu với dữ liệu. Mặc dù bạn không cần khả năng viết truy vấn ở cấp độ cao để tạo và hiểu ERD, nhưng nó vẫn có thể giúp bạn hiểu được tình huống chính xác và DB cũng như cách mọi thứ được kết nối với nhau.
- Tỉ lệ effort/benefit lớn. SQL rất dễ thành thạo. Đó có thể là kỹ năng ‘Át chủ bài’ của bạn, trở thành người tiếp cận những câu hỏi/truy vấn phức tạp.
Thử viết một vài câu lệnh SQL đơn giản
Tôi giả sử rằng các bạn đã quen thuộc với các câu lệnh cơ bản, joins, subqueries.
Ví dụ dưới đây dựa trên một bảng đơn với 5 cột, có kiểu dữ liệu đơn giản. Bảng này đại diện cho các ưu đãi của khách hàng trên các khu vực khác nhau.
|
|
Ta có 20 dòng dữ liệu như dưới đây: Ta tiến hành chèn 20 dòng dữ liệu vào trong bảng trên
|
|
Ta bắt đầu với các truy vấn con:
SELECT deal lớn nhất trong mỗi khu vực.
- Lời giải ngây thơ (naive solution)
|
|
- Cách giải quyết:
- Ta có thể tạo truy vấn con tốt hơn nhưng tôi muốn giới thiệu CTE - Common Table Expression. Một CTE là một bảng tạm thời, nó trông như sau:
|
|
CTE được định nghĩa bằng mệnh đề WITH, theo sau đó là CTE name và sau dó là truy vấn để tạo ra CTE. Sau khi định nghĩa xong có thể chọn CTE như bảng bình thường trong cơ sở dữ liệu.
- Tại sao nó hữu ích?
CTE không cho một khả năng mới (nghĩa là ta có thể giải quyết vấn đề với một truy vấn con thích hợp), nó chỉ hỗ trợ ta viết truy vấn tốt hơn:- Khi sử dụng CTEs, ta không bị rơi vào bẫy truy vấn con liên quan, nó buộc ta phải suy nghĩ về cách giải quyết vấn đề một cách chính xác.
- Nó cải thiện khả năng dễ đọc của câu truy vấn.
Điều thú vị hơn nằm ở dưới đây!!!
Ta sẽ thử sức với câu truy vấn khó hơn một chút.
|
|
Ta nhận được 11 bản ghi, trong khi đó chỉ có 3 khu vực, đáng ra là 9 bản ghi thôi chứ? Ta sẽ hiểu tại sao có điều này sớm thôi!
- Vậy rank/over/partition là những câu lệnh gì mà thú vị như vậy?
- RANK() là một window function. Window function cho phép ta thực hiện các tính toán trên một tập các hàng liên quan tới hàng hiện tại. Một Windows Function được định nghĩa khi có mệnh đề OVER() đi kèm sau lệnh gọi hàm.
- Để tạo ra tập hợp các hàng liên quan, chúng ta sử dụng từ khóa PARTITION BY, chia dữ liệu thành các nhóm. Hiểu đơn giản, Aggregate function có GROUP BY thì Window function có PARTITION BY.
- Lệnh ORDER BY cho phép chúng ta sắp xếp các hàng trong mỗi nhóm.
Các kiểu window function
Có 3 kiểu chính:
- Ranking functions
- Aggregate functions
- Positional functions
- Ranking Window Functions.
- Giống như cái tên của nó, họ xếp hạng các hàng trong mỗi phân vùng. Các Ranking function chính là:
- ROW_NUMBER(): Xếp hạng các giá trị trong từng partition theo thứ tự tăng dần mà không quan tâm đến giá trị giống nhau. Ví dụ: row_number (): 1,2,3,4,5
- RANK(): Xếp hạng các giá trị theo thứ tự tăng dần nhưng sẽ trả về thứ hạng giống nhau với các giá trị giống nhau và bỏ qua thứ hạng đó. Ví dụ: rank(): 1,1,3,4,5
- DENSE_RANK(): Xếp hạng các giá trị theo thứ tự tăng dần nhưng sẽ trả về thứ hạng giống nhau với các giá trị giống nhau và không bỏ qua thứ hạng đó. Ví dụ: dense_rank (): 1,1,2,3,4
|
|
2. Aggregation Window Functions.
- Rất giống với GROUP BY nhưng có một ưu điểm rất lớn là có thể giữ toàn bộ dữ liệu của mỗi dòng.
- Có thể sử dụng tất cả những cái quen thuộc như: SUM(), AVG(), MAX(),…
Với mỗi deal, tính % deal trong mỗi khu vực.
|
|
3. Positional Window Functions
*Các hàm này trả về một giá trị từ một hàng cụ thể trong mỗi window frame. Ví dụ:
- LEAD(): Trả về một giá trị từ một hàng đằng sau hàng hiện tại trong phân vùng.
- LAG(): Trả về một giá trị từ hàng trước hàng hiện tại trong phân vùng.
- FIRST_VALUE(): Trả về giá trị đầu tiên trong phân vùng.
- LAST_VALUE(): Trả về giá trị cuối cùng trong phân vùng.
Đối với mỗi deals, tính toán sự thay đổi về deal_amount so với deals trước đó của cùng một khách hàng trong cùng khu vực.
|
|
Xin hẹn gặp lại các bạn ở các bài viết thú vị hơn nha!!!