SQL là một ngôn ngữ có cú pháp thoạt nhìn thì khá đơn giản, nhưng vì một số lý do nào đó mà bạn chẳng thể làm gì khác ngoài việc google-sama cú pháp đúng cho từng câu truy vấn ngớ ngẩn.
Kế đó, bạn bắt đầu join
chúng, sử dụng các phép tính aggregation, sử dụng các subqueries và rồi bạn thắc mắc tại sao chúng chẳng có ý nghĩa quái gì cả! Vâng, chúng từa tựa như thế này:
1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> members.firstname || <span class="hljs-string">' '</span> || members.lastname <span class="hljs-keyword">AS</span> <span class="hljs-string">"Full Name"</span> <span class="hljs-keyword">FROM</span> borrowings <span class="hljs-keyword">JOIN</span> members <span class="hljs-keyword">ON</span> members.memberid=borrowings.memberid <span class="hljs-keyword">JOIN</span> books <span class="hljs-keyword">ON</span> books.bookid=borrowings.bookid <span class="hljs-keyword">WHERE</span> borrowings.bookid <span class="hljs-keyword">IN</span> (<span class="hljs-keyword">SELECT</span> bookid <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> stock>(<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">avg</span>(stock) <span class="hljs-keyword">FROM</span> books)) <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> members.firstname, members.lastname;</span> |
Bối rối ***! Cái đống này có thể làm bất cứ một gã dev mới vào nghề nào cũng phát hoảng, thậm chí là cả những tay dev tầm trung mới lần đầu nhìn mã SQL.
Thông qua hướng dẫn này, tôi muốn làm cho con đường đến với SQL của những người mới bớt chông gai, kể cả với những người đã làm việc lâu năm với SQL nhưng muốn tìm kiếm một tương lai xán lạn hơn.
Tất cả những câu truy xuất SQL trong bài viết đều viết trên PostgreSQL, mặc dù SQL có cú pháp tương tự nhau trên các cơ sở dữ liệu khác nhau. Do đó, một số cú pháp có thể vẫn hoạt động tốt trên MySQL hay các cơ sở dữ liệu khác.
Nội dung
- Ba từ nhiệm màu ( The three magic words )
- Cơ sở dữ liệu của chúng ta
- Các câu truy vấn đơn giản
- FROM – Chúng ta lấy dữ liệu ở đâu?
- WHERE – Chúng ta lấy dữ liệu ấy qua đâu?
- SELECT – Chúng ta sẽ biểu diễn những gì?
- Joins
- Aggregations
- Subqueries
- Bảng hai chiều
- Mảng một chiều
- Giá trị đơn (Single value)
- Write Operations
- Update
- Delete
- Insert
- Feedback
1. Ba từ nhiệm màu
Mặc dừ có rất nhiều từ khóa được sử dụng trong SQL, SELECT, FROM, WHERE vẫn là 3 từ khóa được sử dụng nhiều nhất. Sau khi đọc tiếp, bạn sẽ dần hình dung được SELECT, FROM, WHERE thể hiện những khía cạnh cơ bản nhất của công việc truy vấn một cơ sở dữ liệu. Bạn cũng sẽ nhận ra rằng những câu truy vấn phức tạp cũng chỉ là SELECT, FROM, WHERE được mở rộng.
2. Cơ sở dữ liệu của chúng ta
Tên cơ sở dữ liệu là Library với bảng books cùng các bảng khác là members, borrowing.
- Bảng books có các cột title, author, published (ngày phát hành), stock – số bản còn lại được sắp xếp khá dễ hiểu.
- Bảng members chỉ có duy nhất tên của các thành viên đã đăng kí.
- Bảng borrowing chứa thông tin những cuốn sách đã được mượn bởi thành viên. Cột
bookid
chính là id của những cuốn sách đã được mượn trong bảng books và cộtmemberid
tương ứng là những thành viên trong bảng “members” đã mượn sách. Chúng ta cũng có cột ngày mượn sách.
3. Câu truy vấn đơn giản
Hãy bắt đầu với câu truy vấn đầu tiên: ta cần names và ids của tất cả các cuốn sách của tác giả Dan Brown. Câu truy vấn:
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> bookid <span class="hljs-keyword">AS</span> <span class="hljs-string">"id"</span>, title <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> author=<span class="hljs-string">'Dan Brown'</span>;</span> |
Kết quả trả về như sau:
id | title |
---|---|
2 | The Lost Symbol |
4 | Inferno |
Ez money! Tuy nhiên, chúng ta cần phân tích cú pháp câu truy vấn trên để hiểu rõ vấn đề:
3.1 FROM – Chúng ta lấy dữ liệu ở đâu?
Với những câu truy vấn đơn giản như trên thì khá rõ ràng, ta sẽ chọn bảng books để lấy dữ liệu. Tuy nhiên khi đi sâu vào các truy vấn JOIN và các subquery thì vấn đề trở nên khó khăn hơn. Định nghĩa của khóa FROM là nó sẽ chỉ ra bảng nơi mà các câu truy vấn cần tìm kiếm dữ liệu phù hợp. Bảng có thể đã tồn tại rồi, hoặc là bảng tạo bởi câu lệnh JOIN hay từ các subqueries.
3.2 WHERE – Chúng ta lấy dữ liệu ấy qua đâu?
Từ khóa này dùng điều kiện và lọc ra hàng phù hợp với điều kiện ấy. Trong trường hợp của chúng ta thì những hàng trả về sẽ nằm ở cột author và có giá trị “Dan Brown”.
3.3 SELECT – Chúng ta sẽ biểu diễn những gì?
Giả sử chúng ta đã có đầy đủ những bảng dữ liệu phù hợp. Vấn đề là lấy những dữ liệu cần thiết như thế nào? Ta cần id và name của những cuốn sách, vậy ta sẽ SELECT chúng. Chúng ta cũng có thể đổi tên hiện thị của cột bằng từ khóa AS (tên gốc trong bảng không thay đổi).
4. Joins
Bây giờ nếu cần tất cả tên của các cuốn sách đã được mượn của tác giả Dan Brown cùng với ngày mượn, ta sử dụng câu truy vấn sau (lưu ý rằng có thể có sự lặp lại):
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> books.title <span class="hljs-keyword">AS</span> <span class="hljs-string">"Title"</span>, borrowings.returndate <span class="hljs-keyword">AS</span> <span class="hljs-string">"Return Date"</span> <span class="hljs-keyword">FROM</span> borrowings <span class="hljs-keyword">JOIN</span> books <span class="hljs-keyword">ON</span> borrowings.bookid=books.bookid <span class="hljs-keyword">WHERE</span> books.author=<span class="hljs-string">'Dan Brown'</span>;</span> |
Kết quả trả về:
Title | Return Date |
---|---|
The Lost Symbol | 2016-03-23 00:00:00 |
Inferno | 2016-04-13 00:00:00 |
The Lost Symbol | 2016-04-19 00:00:00 |
Hẳn các bạn đã quen thuộc với cú pháp trên, ngoại trừ sau phần FROM: bảng chúng ta truy vấn đến đã thay đổi. Bây giờ bảng mới không phải borrowing hay books mà là 1 bảng mới, kết hợp cả 2 bảng trên.
Cú pháp borrowings JOIN books ON borrowings.bookid=books.bookid được xem như 1 bảng mới, tổng hợp tất cả các mục của 2 bảng borrowing và books, miễn là các mục có cùng bookid
ở mỗi bảng. Bảng tổng hợp như sau:
Chúng ta chỉ cần truy vấn đến dữ liệu trong bảng mới này tương tự như truy vấn ở những bảng đơn. Vấn đề đã trở nên đơn giản hơn: chúng ta chỉ cần quan tâm rằng nên JOIN
các bảng như thế nào. Tùy thuộc vào cách chúng ta JOIN
bảng mà mức độ phức tạp của các câu truy vấn cũng sẽ giảm.
Bây giờ hãy thử 1 ví dụ khó hơn một chút:
- Ta cần biết tên của những người đã mượn sách của Dan Brown.
Lần này chúng ta sẽ thử phương pháp suy luận ngược để giải quyết bài toán:
Bước 1: ta sẽ lấy dữ liệu từ đâu? Cần phải JOIN
bảng members, bảng books và bảng borrowing với nhau. Câu truy vấn:
1 2 3 |
borrowings JOIN books ON borrowings.bookid=books.bookid JOIN members ON members.memberid=borrowings.memberid |
Bảng kết quả trả về:
Bước 2: Biểu diễn dữ liệu gì? Cần tập trung vào những dữ liệu có yếu tố author là “Dan Brown”.
1 |
<span class="hljs-constant">WHERE</span> books.author=<span class="hljs-string">'Dan Brown'</span> |
Bước 3: Biểu diễn dữ liệu lấy được như thế nào? Bây giờ dữ liệu đã đầy đủ,ta cần biểu diễn tên của những thành viên mượn sách.
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> members.firstname <span class="hljs-keyword">AS</span> <span class="hljs-string">"First Name"</span>, members.lastname <span class="hljs-keyword">AS</span> <span class="hljs-string">"Last Name"</span></span> |
Công việc bây giờ chỉ đơn giản là kết hợp 3 bước để hoàn thiện truy vấn. Cú pháp đầy đủ như sau:
1 2 3 4 5 6 7 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> members.firstname <span class="hljs-keyword">AS</span> <span class="hljs-string">"First Name"</span>, members.lastname <span class="hljs-keyword">AS</span> <span class="hljs-string">"Last Name"</span> <span class="hljs-keyword">FROM</span> borrowings <span class="hljs-keyword">JOIN</span> books <span class="hljs-keyword">ON</span> borrowings.bookid=books.bookid <span class="hljs-keyword">JOIN</span> members <span class="hljs-keyword">ON</span> members.memberid=borrowings.memberid <span class="hljs-keyword">WHERE</span> books.author=<span class="hljs-string">'Dan Brown'</span>;</span> |
Bảng kết quả trả về:
First Name | Last Name |
---|---|
Mike | Willis |
Ellen | Horton |
Ellen | Horton |
Tuy nhiên có những tên bị trùng. Kế tiếp ta sẽ xử lí chúng.
5. Aggregations
Nói 1 cách ngắn gọn, aggregation (phép gộp) được sử dụng để chuyển nhiều hàng thành 1 hàng. Aggregation sẽ chỉ làm thay đổi logic của các cột sử dụng gộp dữ liệu.
Hãy tiếp tục với ví dụ trước, khi kết quả “Ellen Horton” bị lặp. Ta sẽ viết truy vấn khác:
1 2 3 4 5 6 7 8 9 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> members.firstname <span class="hljs-keyword">AS</span> <span class="hljs-string">"First Name"</span>, members.lastname <span class="hljs-keyword">AS</span> <span class="hljs-string">"Last Name"</span>, <span class="hljs-keyword">count</span>(*) <span class="hljs-keyword">AS</span> <span class="hljs-string">"Number of books borrowed"</span> <span class="hljs-keyword">FROM</span> borrowings <span class="hljs-keyword">JOIN</span> books <span class="hljs-keyword">ON</span> borrowings.bookid=books.bookid <span class="hljs-keyword">JOIN</span> members <span class="hljs-keyword">ON</span> members.memberid=borrowings.memberid <span class="hljs-keyword">WHERE</span> books.author=<span class="hljs-string">'Dan Brown'</span> <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> members.firstname, members.lastname;</span> |
Kết quả trả về:
First Name | Last Name | Number of books borrowed |
---|---|---|
Mike | Willis | 1 |
Ellen | Horton | 2 |
Hầu hết trong mọi tình huống dùng phép gộp ta đều sử dụng khóa GROUP BY. Khóa này dùng để xếp các dữ liệu giống nhau thành nhóm. Mỗi nhóm tương ứng với 1 nhóm các giá trị duy nhất có đặc điểm nêu sau khóa GROUP BY. Cụ thể, trong ví dụ trên ta đã chuyển dữ liệu thu được vào nhóm các hàng. Ta cũng đã sử dụng hàm gộp count. Hàm count sẽ chuyển nhiều hàng vào 1 giá trị đơn (trong trường hợp này là số hàng).
Mỗi hàng ở bảng sau biểu diễn kết quả sau khi gộp của từng nhóm.
Ngoài hàm count, chúng ta còn có hàm sum hay max. Ví dụ, nếu ta muốn tính tổng số sách của từng tác giả, ta viết:
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> author, <span class="hljs-keyword">sum</span>(stock) <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> author;</span> |
Kết quả trả về như sau:
author | sum |
---|---|
Robin Sharma | 4 |
Dan Brown | 6 |
John Green | 3 |
Amish Tripathi | 2 |
Trên đây là hàm SUM, nó chỉ làm việc trên cột stock, nó dùng để tính tổng các giá trị trong mỗi nhóm.
6. Subqueries
Subqueries – truy vấn con, là những câu truy vấn SQL bình thường, tuy nhiên nó được thêm vào bên trong những câu truy vấn lớn.
Có 3 loại subqueries khác nhau dựa trên kiểu chúng trả về.
6.1 Bảng hai chiều
Là những câu truy vấn trả về kết quả nhiều hơn 1 cột. Hãy xem lại các bảng kết quả mà chúng ta đã có.
author | sum |
---|---|
Robin Sharma | 4 |
Dan Brown | 6 |
John Green | 3 |
Amish Tripathi | 2 |
Bây giờ thử viết truy vấn lấy dữ liệu từ bảng này, ta sẽ được một bảng mới có cấu trúc bé hơn ( ít hàng, ít cột hơn). Tuy nhiên, khi sử dụng subqueries, t chỉ cần viết truy vấn 1 lần và bỏ qua được bước tạo bảng trên, nhảy thẳng đến bảng kết quả cuối cùng:
1 2 3 4 5 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> author, <span class="hljs-keyword">sum</span>(stock) <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> author) <span class="hljs-keyword">AS</span> results <span class="hljs-keyword">WHERE</span> author=<span class="hljs-string">'Robin Sharma'</span>;</span> |
Kết quả:
author | sum |
---|---|
Robin Sharma | 4 |
6.2 Mảng một chiều
Những câu truy vấn trả về nhiều hàng của chỉ 1 cột, kết quả thu được có thể biểu diễn theo dạng mảng.
Ví dụ, chúng ta cần tiêu đề và id của tất cả các cuốn sách của 1 tác giả, với điều kiện số sách phải lớn hơn 3. Hãy chia nhỏ vấn đề để giải quyết:
Bước 1: Lấy dữ liệu tác giả có số sách lớn hơn 3
1 2 3 4 5 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> author <span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> author, <span class="hljs-keyword">sum</span>(stock) <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> author) <span class="hljs-keyword">AS</span> results <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">sum</span> > <span class="hljs-number">3</span>;</span> |
Kết quả trả về:
author |
---|
Robin Sharma |
Dan Brown |
Kết quả này có thể viết: [‘Robin Sharma’, ‘Dan Brown’]
Bước 2: Bây giờ hãy dùng kết quả trên để truy vấn tiếp:
1 2 3 4 5 6 7 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> title, bookid <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> author <span class="hljs-keyword">IN</span> (<span class="hljs-keyword">SELECT</span> author <span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> author, <span class="hljs-keyword">sum</span>(stock) <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> author) <span class="hljs-keyword">AS</span> results <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">sum</span> > <span class="hljs-number">3</span>);</span> |
Trả về kết quả:
title | bookid |
---|---|
The Lost Symbol | 2 |
Who Will Cry When You Die? | 3 |
Inferno | 4 |
Viết gọn lại theo kiểu mảng:
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> title, bookid <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> author <span class="hljs-keyword">IN</span> (<span class="hljs-string">'Robin Sharma'</span>, <span class="hljs-string">'Dan Brown'</span>);</span> |
6.3 Single Values
Có những câu truy vấn chỉ trả về kết quả là 1 hàng, 1 cột. Kết quả này có thể xem như là giá trị không đổi (hằng) và có thể được sử dụng trong các phép so sánh. Nó cũng được xem như mảng 1 chiều chỉ 1 phần tử, hay bảng hai chiều.
Hãy tiếp tục với các ví dụ, tìm cuốn sách có số lượng lớn hơn số lượng sách trung bình.
1 |
<span class="hljs-operator"><span class="hljs-keyword">select</span> <span class="hljs-keyword">avg</span>(stock) <span class="hljs-keyword">from</span> books;</span> |
Kết quả trả về:
avg |
---|
3.000 |
Nó có thể được sử dụng như giá trị vô hướng 3.
Hãy đến với câu truy vấn tiếp theo:
1 2 3 4 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> stock>(<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">avg</span>(stock) <span class="hljs-keyword">FROM</span> books);</span> |
Nó tương đương với câu truy vấn sau:
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> stock><span class="hljs-number">3.000</span></span> |
Kết quả trả về:
bookid | title | author | published | stock |
---|---|---|---|---|
3 | Who Will Cry When You Die? | Robin Sharma | 2006-06-15 00:00:00 | 4 |
7. Write Operations
Hầu hết từ khóa dùng trong SQL đều đơn nghĩa, dễ hiểu. Ngoài các từ khóa đã tìm hiểu thì còn có các từ khóa khác như UPDATE, DELETE, INSERT.
7.1 Update
Cấu trúc truy vấn không quá rắc rối, chỉ khác là bạn sẽ thay đổi dữ liệu ở nơi chỉ định chứ không phải xuất dữ liệu.
Trở về với ví dụ, nếu bỗng nhiên chúng ta bị mất hết các cuốn sách của Dan Brown, ta cần thay đổi dữ liệu số sách trở thành 0.
1 2 3 |
<span class="hljs-operator"><span class="hljs-keyword">UPDATE</span> books <span class="hljs-keyword">SET</span> stock=<span class="hljs-number">0</span> <span class="hljs-keyword">WHERE</span> author=<span class="hljs-string">'Dan Brown'</span>;</span> |
Từ khóa WHERE vẫn được sử dụng như bình thường, chỉ ra vị trí mà dữ liệu được cập nhật. Trong trường hợp này, ở bảng books, tất cả các hàng có tên tác giả là Dan Brown sẽ được đặt lại giá trị ở cột stock bằng 0.
7.2 Delete
Một câu truy vấn DELETE chỉ đơn giản là 1 câu truy vấn SELECT hay UPDATE nhưng không có tên cột. WHERE cũng sẽ chỉ ra nơi dữ liệu bị xóa. Sau khi câu truy vấn được thực thi, xóa hoàn toàn 1 hàng dữ liệu, hàng dữ liệu trở nên rỗng, không thể cập nhật hay thêm sửa xóa gì. Nó khác với việc dùng từ khóa UPDATE.
Do đó nếu muốn xóa hoàn toàn dữ liệu từ tác giả Dan Brown, ta chỉ cần dùng DELETE:
1 2 |
<span class="hljs-operator"><span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> author=<span class="hljs-string">'Dan Brown'</span>;</span> |
7.3 Insert
Cấu trúc của câu truy vấn INSERT:
1 2 3 4 |
<span class="hljs-operator"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> x (a,b,c) <span class="hljs-keyword">VALUES</span> (x, y, z);</span> |
a
, b
, c
là tên các cột, x
, y
, và z
là giá trị được chèn vào các cột tương ứng.
Dưới đây là ví dụ cụ thể của truy vấn INSERT để chèn thêm dữ liệu vào bảng books:
1 2 3 4 5 6 7 8 |
<span class="hljs-operator"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> books (bookid,title,author,published,stock) <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">1</span>,<span class="hljs-string">'Scion of Ikshvaku'</span>,<span class="hljs-string">'Amish Tripathi'</span>,<span class="hljs-string">'06-22-2015'</span>,<span class="hljs-number">2</span>), (<span class="hljs-number">2</span>,<span class="hljs-string">'The Lost Symbol'</span>,<span class="hljs-string">'Dan Brown'</span>,<span class="hljs-string">'07-22-2010'</span>,<span class="hljs-number">3</span>), (<span class="hljs-number">3</span>,<span class="hljs-string">'Who Will Cry When You Die?'</span>,<span class="hljs-string">'Robin Sharma'</span>,<span class="hljs-string">'06-15-2006'</span>,<span class="hljs-number">4</span>), (<span class="hljs-number">4</span>,<span class="hljs-string">'Inferno'</span>,<span class="hljs-string">'Dan Brown'</span>,<span class="hljs-string">'05-05-2014'</span>,<span class="hljs-number">3</span>), (<span class="hljs-number">5</span>,<span class="hljs-string">'The Fault in our Stars'</span>,<span class="hljs-string">'John Green'</span>,<span class="hljs-string">'01-03-2015'</span>,<span class="hljs-number">3</span>);</span> |
8. Feedback
Cuối cùng thì cũng cuối tuần. Kết thúc mỗi phiên truy vấn ta nên kiểm tra lại cấu trúc truy vấn cũng như tính dễ đọc của nó:
1 2 3 4 5 6 7 8 9 10 11 |
<span class="hljs-operator"><span class="hljs-keyword">SELECT</span> members.firstname || <span class="hljs-string">' '</span> || members.lastname <span class="hljs-keyword">AS</span> <span class="hljs-string">"Full Name"</span> <span class="hljs-keyword">FROM</span> borrowings <span class="hljs-keyword">JOIN</span> members <span class="hljs-keyword">ON</span> members.memberid=borrowings.memberid <span class="hljs-keyword">JOIN</span> books <span class="hljs-keyword">ON</span> books.bookid=borrowings.bookid <span class="hljs-keyword">WHERE</span> borrowings.bookid <span class="hljs-keyword">IN</span> (<span class="hljs-keyword">SELECT</span> bookid <span class="hljs-keyword">FROM</span> books <span class="hljs-keyword">WHERE</span> stock> (<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">avg</span>(stock) <span class="hljs-keyword">FROM</span> books) ) <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> members.firstname, members.lastname;</span> |
Hiển nhiên kết quả trả về sẽ là danh sách người mượn sách với số lượng sách mượn trên trung bình:
Full Name |
---|
Lida Tyler |