EXISTS, NOT EXISTS, GROUP BY, JOIN, UNION, UNION ALL trong SQL

EXISTS, NOT EXISTS, GROUP BY, JOIN, UNION, UNION ALL trong SQL

Tags
MySQL
Published
January 23, 2024
Author

Cú pháp EXISTS và NOT EXISTS

 
SELECT column_name
FROM table_name
WHERE [NOT] EXISTS
(SELECT column_name
FROM table_name
WHERE condition)
 
Subquery trả về giá trị True hoặc False

Ví dụ: Lấy họ và tên của customer đã đặt ít nhất 1 đơn hàng

 
Cho 2 bảng:
  • Bảng customers: fname, lname
  • Bảng orders: order_id, customer_id
 
SELECT fname, lname
FROM customers
WHERE EXISTS
(SELECT *
FROM orders
WHERE customers.customer_id = orders.customer_id)
 

Xóa bản ghi các dòng trong bảng order khi customer có họ là ‘Mehra’.

 
DELETE *
FROM customer
WHERE EXISTS
(SELECT *
FROM customer
WHERE customer.customer_id=orders.customer_id AND customer.lname = ‘Mehra’
 

Cú pháp Group By

 
SELECT column1, SUM (column2)
FROM table_name
WHERE condition
GROUP BY col1, col2
HAVING condition
ORDER BY col1, col2
 
Group by with Count, Aggregate functions (Max, Min, Avg…)

Bài tập

Write a query to list the name of courses that do not have a book published in 2014. Set the header for the single column of results, to be name.

 
Bảng students
id
name
age
grade
marks
courseId
studentMentorId
1
Johnson
12
6
80
1
2
Harding
6
1
94
2
16
3
Taft
7
2
77
3
4
Hoover
13
7
30
4
9
5
Lincoln
12
6
81
5
6
Garfield
15
9
91
6
10
7
Polk
12
6
49
7
8
Grant
16
10
25
8
9
Bruce
13
7
51
3
10
Tony
14
9
81
1
22
11
Peter
15
10
5
3
8
12
Andrew
18
12
49
6
13
Edgar
8
24
4
14
Abraham
13
26
5
11
15
Hugh
16
10
12
16
Tonya
1
6
2
17
Murray
14
91
7
15
18
Descartes
12
6
28
8
19
Cisco
12
6
65
13
18
20
Barry
13
7
42
12
21
Kara
15
8
12
25
22
Oliver
16
9
86
11
23
Kate
17
10
55
9
24
24
Cobb
18
11
59
20
25
Paige
19
12
98
3
Bảng courses
id
name
abbreviatedName
1
JavaScript
js
2
Java
java
3
Python
py
4
Ruby
rb
5
Rust
rs
6
C#
cs
7
SQL
sql
8
PHP
php
9
C++
cpp
10
C
c
11
Objective-C
objc
12
Swift
swft
13
Scala
sc
Bảng books
id
name
price
publishedIn
publisherName
courseID
authorID
nextVolumeId
1
Basics of JavaScript - Volume 1
647
2015
Monarch Press
1
10
13
2
Basics of Java - Volume 1
491
2012
HYDRA Inc.
2
5
4
3
Advanced Python - The Ultimate Edition
531
2010
SHIELD Books
3
8
4
Basics of Java - Volume 2
995
2013
HYDRA Inc.
2
5
9
5
Objective-C for Beginners - 1st Edition
722
2017
Ten Rings Pvt Ltd
11
2
32
6
C++ Basics - Volume 1
165
2014
SHIELD Books
9
1
7
7
C++ Basics - Volume 2
320
2014
SHIELD Books
9
1
8
Basics of Rust
614
2018
AIM Books
5
4
9
Basics of Java - Volume 3
515
2014
HYDRA Inc.
2
5
15
10
Building Basic Apps in Ruby - Part 1
194
2013
Ten Rings Pvt Ltd
4
6
11
11
Building Basic Apps in Ruby - Part 2
236
2013
Ten Rings Pvt Ltd
4
8
12
12
Building Basic Apps in Ruby - Part 3
178
2014
Ten Rings Pvt Ltd
4
6
13
Basics of JavaScript - Volume 2
799
2017
Monarch Press
1
9
14
Advanced Concepts in Rust - Part 1
113
2018
AIM Books
5
4
16
15
Basics of Java - Volume 4
142
2016
HYDRA Inc.
2
5
16
Advanced Concepts in Rust - Part 2
851
2019
AIM Books
5
4
17
Basics of Python - The Ultimate Edition
612
2011
SHIELD Books
3
8
18
JAVA for Professionals
724
2011
HYDRA Inc.
2
5
19
Advanced Algorithms in C++ - The Ultimate Edition
193
2015
SHIELD Books
9
1
20
PHP for Beginners and Professionals - The Ultimate Guide
199
2010
Monarch Press
8
3
21
Advanced Scala for Research - Volume 1
593
2013
Monarch Press
13
6
23
22
Introduction to Elixir on Phoenix
603
2013
AIM Books
10
23
Advanced Scala for Research - Volume 2
599
2014
Monarch Press
13
6
24
Advanced JavaScript, The Collector's Edition
632
2016
Monarch Press
1
9
25
Advanced Java - Volume 1
998
2014
HYDRA Inc.
2
5
26
26
Advanced Java - Volume 2
234
2015
HYDRA Inc.
2
5
27
Building Apps with Ruby on Rails - Part 1
104
2015
Ten Rings Pvt Ltd
4
6
30
28
C# and ASP.NET - The Beginners Edition
786
2008
HYDRA Inc.
6
29
Basic Concepts in Elm - Volume 1
297
2011
AIM Books
34
30
Building Apps with Ruby on Rails - Part 2
164
2015
Ten Rings Pvt Ltd
4
6
31
C# and ASP.NET - The Professionals Edition
156
2009
HYDRA Inc.
6
1
32
Objective-C for Beginners - 2nd Edition
324
2018
Ten Rings Pvt Ltd
11
2
33
Basics of Scala
889
2014
Monarch Press
13
6
34
Basic Concepts in Elm - Volume 2
155
2012
AIM Books
6
Bảng authors
id
name
gender
codeName
1
Steve Strange
M
Phil
2
Bruce Quill
M
Grant
3
Natasha Rogers
F
Melinda
4
Clint Banner
M
Barry
5
Wanda Romanoff
F
Simmons
6
Tony Barton
M
Leo
7
Scott Maximoff
M
Garfield
8
Hope Stark
F
Tonya
9
Stephen Lang
M
Odin
10
Peter Pym
M
Bilbo
 
SELECT name FROM courses WHERE NOT EXISTS (SELECT * FROM books WHERE books.courseID=courses.id AND books.publishedIn = '2014');
 

Find maximum marks obtained by students in each grade.

 
Bảng students
id
name
age
grade
course
marks
1
Johnson
12
6
JavaScript
80
2
Harding
6
1
Java
94
3
Taft
7
2
Python
77
4
Hoover
13
7
Ruby
30
5
Lincoln
12
6
Rust
81
6
Garfield
15
9
C#
91
7
Polk
12
6
SQL
49
8
Grant
16
10
PHP
25
9
Bruce
13
7
Python
51
10
Tony
14
9
JavaScript
81
11
Peter
15
10
Python
5
12
Andrew
18
12
C#
49
13
Edgar
8
Ruby
24
14
Abraham
13
Rust
26
15
Hugh
16
10
12
16
Tonya
1
Java
6
17
Murray
SQL
91
18
Descartes
12
6
PHP
28
SELECT grade, MAX(marks) FROM students WHERE grade IS NOT NULL GROUP BY grade
 

SELF JOIN?

The table students contains a column studentMentorId. It stores the id of another student who is a mentor of the student in a particular row.
Let's say we want to display the name of all students who have a mentor, along with the name of their mentors. Let's name the headers studentName and mentorName respectively.
In this case, the data for both our result columns, belongs to one and the same column in students, i.e. name. So, we need join the table students with itself. This kind of a JOIN is called a SELF JOIN.
 
id
name
age
grade
marks
courseId
studentMentorId
1
Johnson
12
6
80
1
2
Harding
6
1
94
2
16
3
Taft
7
2
77
3
4
Hoover
13
7
30
4
9
5
Lincoln
12
6
81
5
6
Garfield
15
9
91
6
10
7
Polk
12
6
49
7
8
Grant
16
10
25
8
9
Bruce
13
7
51
3
10
Tony
14
9
81
1
22
11
Peter
15
10
5
3
8
12
Andrew
18
12
49
6
13
Edgar
8
24
4
14
Abraham
13
26
5
11
15
Hugh
16
10
12
16
Tonya
1
6
2
17
Murray
14
91
7
15
18
Descartes
12
6
28
8
19
Cisco
12
6
65
13
18
20
Barry
13
7
42
12
21
Kara
15
8
12
25
22
Oliver
16
9
86
11
23
Kate
17
10
55
9
24
24
Cobb
18
11
59
20
25
Paige
19
12
98
3
SELECT s1.name AS studentName, s2.name AS mentorName FROM students s1 JOIN students s2 ON s1.studentMentorId = s2.id
 

Khi nào dùng UNION hay UNION ALL?

Dùng lại bảng books và students từ các ví dụ trên.
 
Let's say, we want to print id cards for all the students and all the books. An id card for a student will just have the student's id, and an id card for a book will just contain the book's id. For this, we have to print all the ids in a single result, under a single column.
 
SELECT id FROM students UNION SELECT id FROM books
 
The ids for students range from 1 to 25, and for books, range from 1 to 34.
The results of the above query are just 1 to 34.
This helps explain that if there are matching records from multiple queries in a UNION, only one of them will be included in the final results. That's another way of saying that the results of a UNION are always unique.
Then how do we solve our problem? We need all 25 student ids and all 34 book ids. In such cases, there is an extension to UNION, called UNION ALL.
 
SELECT id FROM students UNION ALL SELECT id FROM books
 
Xem thêm về EXCEPT và INTERSECT.

Bài tập lớn

CREATE DATABASE nhasachnhanam; USE nhasachnhanam; CREATE TABLE dm_sach (ma_dmsach INT PRIMARY KEY AUTO_INCREMENT, the_loai VARCHAR(50), mo_ta VARCHAR (50));
CREATE TABLE dm_dochoi (ma_dmdochoi INT PRIMARY KEY AUTO_INCREMENT, nhom VARCHAR(50), mo_ta VARCHAR (50));
CREATE TABLE dm_dungcu (ma_dmdungcu INT PRIMARY KEY AUTO_INCREMENT, khoi VARCHAR(50), mo_ta VARCHAR (50));
CREATE TABLE sanpham_sach (masp_sach VARCHAR(50) PRIMARY KEY, tensp_sach VARCHAR(50), so_luong INT, don_gia INT, don_vi VARCHAR(50), ma_dmsach INT, FOREIGN KEY (ma_dmsach) REFERENCES dm_sach(ma_dmsach), nha_xuat_ban VARCHAR(50), nam_xuat_ban YEAR, tac_gia VARCHAR(50), ngay_xuat_ban DATETIME, lan_tai_ban INT);
CREATE TABLE sanpham_dochoi (masp_dochoi VARCHAR(50) PRIMARY KEY, tensp_dochoi VARCHAR(50), so_luong INT, don_gia INT, don_vi VARCHAR(50), ma_dmdochoi INT, FOREIGN KEY (ma_dmdochoi) REFERENCES dm_dochoi(ma_dmdochoi), xuat_su VARCHAR(50), thuong_hieu VARCHAR(50), nha_cung_cap VARCHAR(50), huong_dan VARCHAR(50));
 
INSERT INTO sanpham_dungcu (masp_dungcu, tensp_dungcu, so_luong, don_gia, don_vi, ma_dmdungcu, xuat_su, thuong_hieu, nha_cung_cap, mau_sac, kich_thuoc, chat_lieu, huong_dan)
VALUES ('Dungcu1','Vo',100,4000, 'VND', 1, 'Thai Lan', 'ZZZ', 'Trang Tien', 'Xanh', 'S', 'Giay', 'AAA'), ('Dungcu2','Dong ho',6000,2000000, 'VND', 2, 'My', 'YYY', 'Dong Hoi', 'Do', 'L', 'Go', 'BBB'), ('Dungcu3','May tinh',10,10000000, 'VND', 3, 'Duc', 'NNN', 'Ha Anh', 'Xam', 'M', 'Nhua', 'DDD');
 

SQL liên quan gì đến Testing?

Ví dụ bạn có chức năng tạo mới userhiển thị list user chính xác.
Tuy nhiên chức năng list user chưa hoàn thiện nên khi tạo mới user xong bạn có thể xác nhận bằng cách kiểm tra trong database xem đã tạo bản ghi mới là lưu đúng các trường, đúng value hay chưa.
 
Việc lưu trữ các thông tin bằng excel thì quản lý rất khó khăn. Trong trường hợp bạn muốn thêm hay sửa xóa thông tin ai đó sẽ mất nhiều thời gian. SQL sẽ giúp bạn quản lý và truy vấn thông tin nhanh hơn và bảo trì thông tin cũng dễ dàng hơn.
 
Có rất nhiều test case đòi hỏi môi trường test trong sạch (tức là clear hết dữ liệu), thay vì ngồi xóa thủ công mất rất nhiều thời gian, thậm chí có những dữ liệu không thể xóa trên giao diện, bạn nên sử dụng câu lệnh Delete để tiết kiệm thời gian và đảm bảo dữ liệu được dọn dẹp sạch sẽ.
 
Dummy Data: Bạn tạo ra 1 bộ data test với những data bạn cần. Khi tạo data, mình dùng câu lệnh INSERT, hoặc những website như https://www.mockaroo.com/ sẽ giúp bạn làm chuyện này tốt hơn.

Tham khảo