Để học tốt bài này, các bạn cần đọc 2 bài này trước:
- Tạo database và tạo table trong MySQL với Python
- Thêm (insert) và xóa (delete) dữ liệu trong MySQL với Python
Lưu ý, chúng ta đang sử dụng MySQL được tích hợp sẵn trong XAMPP. Các bạn cần đọc lại bài Cài đặt môi trường lập trình Web PHP với XAMPP để biết cách cài đặt XAMPP và khởi chạy MySQL.
1. Tạo các table để minh họa câu lệnh JOIN trong MySQL
Chúng ta có thể kết hợp các dòng (gọi là row hoặc record) của 2 hoặc nhiều table dựa trên những cột (column) liên quan giữa chúng trong MySQL bằng cách sử dụng câu lệnh JOIN. Có những loại câu lệnh JOIN khác nhau:
(INNER) JOIN
: Trả về các record có những giá trị phù hợp trong cả hai bảng.LEFT (OUTER) JOIN
: Trả về tất cả record từ bảng bên trái và những record có giá trị phù hợp từ bảng bên phải.RIGHT (OUTER) JOIN
: Trả về tất cả record từ bảng bên phải và những record có giá trị phù hợp với bản bên trái.
Trong bài này, chúng ta sẽ tạo và insert dữ liệu cho 2 table gochocit_posts và gochocit_comments trong database gochocit để thực hiện các minh họa sử dụng câu lệnh JOIN.
1.1. Tạo và insert dữ liệu cho table gochocit_posts
import mysql.connector
# create connection to MySQL
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="",
database = "gochocit"
)
mycursor = mydb.cursor()
# create table gochocit_posts
sql_string = """CREATE TABLE IF NOT EXISTS gochocit_posts (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
post_author VARCHAR(255),
post_title TEXT,
post_content TEXT,
post_date DATETIME
)
"""
mycursor.execute(sql_string)
# insert data for table gochocit_posts
sql = """INSERT INTO gochocit_posts (post_author, post_title, post_content, post_date)
VALUES (%s, %s, %s, %s)
"""
val = [
("Vinh Lê", "Kết nối MySQL", "Cách kết nối MySQL sử dụng Python", "2022-03-27 19:46:05"),
("Vinh Lê", "Insert data vào table", "Sử dụng câu lệnh INSERT INTO", "2022-03-27 19:47:06"),
("Vinh Lê", "Drop table", "Xóa table trong MySQL", "2022-03-27 19:48:07")
]
mycursor.executemany(sql, val)
mydb.commit()
# disconnect from MySQL
mydb.close()
ID trong table gochocit_posts sẽ tự động tăng. ID được thêm vào của 3 dòng vừa insert là 6, 7, 8 chứ không phải 1, 2, 3. Bởi vì đã từng có 5 dòng đã được insert nhưng sau đó đã bị xóa đi.
1.2. Tạo và insert dữ liệu cho table gochocit_comments
import mysql.connector
# create connection to MySQL
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="",
database = "gochocit"
)
mycursor = mydb.cursor()
# create table gochocit_comments
sql_string = """CREATE TABLE IF NOT EXISTS gochocit_comments (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
post_ID INT NOT NULL,
comment_author VARCHAR(255),
comment_content TEXT,
comment_date DATETIME
)
"""
mycursor.execute(sql_string)
# insert data for table gochocit_comments
sql = """INSERT INTO gochocit_comments (post_ID, comment_author, comment_content, comment_date)
VALUES (%s, %s, %s, %s)
"""
val = [
("7", "SuperMan", "Good job, thanks.", "2022-03-29 10:46:05"),
("7", "Ahihi", "Hay đấy!", "2022-03-29 11:47:06"),
("8", "Nam Trần", "Dễ hiểu.", "2022-03-29 11:48:07")
]
mycursor.executemany(sql, val)
mydb.commit()
# disconnect from MySQL
mydb.close()
Chúng ta có thể sử dụng cột ID của bảng gochocit_posts và cột post_ID của bảng gochocit_comments để kết hợp 2 bảng này.
2. Câu lệnh INNER JOIN trong MySQL
Sử dụng INNER JOIN
để xem những bài post nào có những comment nào. Những bài post không có comment thì sẽ không được hiển thị.
import mysql.connector
# create connection to MySQL
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="",
database = "gochocit"
)
mycursor = mydb.cursor()
sql = """SELECT
gochocit_posts.ID,
gochocit_posts.post_title,
gochocit_comments.comment_author,
gochocit_comments.comment_content
FROM gochocit_posts
INNER JOIN gochocit_comments ON gochocit_posts.ID = gochocit_comments.post_ID
"""
mycursor.execute(sql)
myresult = mycursor.fetchall()
print("Displaying ID, Post Title, Comment Author and Comment Content:")
for x in myresult:
print(x)
# disconnect from MySQL
mydb.close()
Kết quả
Displaying ID, Post Title, Comment Author and Comment Content:
(7, 'Insert data vào table', 'SuperMan', 'Good job, thanks.')
(7, 'Insert data vào table', 'Ahihi', 'Hay đấy!')
(8, 'Drop table', 'Nam Trần', 'Dễ hiểu.')
Lưu ý: Chúng ta có thể sử dụng JOIN thay vì INNER JOIN. Hai câu lệnh này sẽ cho kết quả như nhau.
3. Câu lệnh LEFT JOIN trong MySQL
Nếu chúng ta muốn xem tất cả bài post kể cả bài post đó có comment hay không có comment thì sử dụng LEFT JOIN
.
sql = """SELECT
gochocit_posts.ID,
gochocit_posts.post_title,
gochocit_comments.comment_author,
gochocit_comments.comment_content
FROM gochocit_posts
LEFT JOIN gochocit_comments ON gochocit_posts.ID = gochocit_comments.post_ID
"""
Kết quả
Displaying ID, Post Title, Comment Author and Comment Content:
(7, 'Insert data vào table', 'SuperMan', 'Good job, thanks.')
(7, 'Insert data vào table', 'Ahihi', 'Hay đấy!')
(8, 'Drop table', 'Nam Trần', 'Dễ hiểu.')
(6, 'Kết nối MySQL', None, None)
Bài post có ID=6
không có comment nào cũng được hiển thị.
4. Câu lệnh RIGHT JOIN trong MySQL
Giả sử, chúng ta thêm 1 dòng dữ liệu vào table gochocit_comments như bên dưới.
Chúng ta muốn xem tất cả comment và những comment nào thuộc bài post nào, xem cả những bài comment không thuộc bài post nào cả thì sử dụng RIGHT JOIN
.
sql = """SELECT
gochocit_posts.ID,
gochocit_posts.post_title,
gochocit_comments.comment_author,
gochocit_comments.comment_content
FROM gochocit_posts
RIGHT JOIN gochocit_comments ON gochocit_posts.ID = gochocit_comments.post_ID
"""
Kết quả
Displaying ID, Post Title, Comment Author and Comment Content:
(7, 'Insert data vào table', 'SuperMan', 'Good job, thanks.')
(7, 'Insert data vào table', 'Ahihi', 'Hay đấy!')
(8, 'Drop table', 'Nam Trần', 'Dễ hiểu.')
(None, None, 'Kane', 'Thank you for sharing.')
Comment (None, None, 'Kane', 'Thank you for sharing.')
không thuộc bài post nào cũng được hiển thị.
Lưu ý: Sẽ là không hợp lý (make sense) khi một comment không thuộc bài post nào. Nhưng có thể rơi vào trường hợp, bài post đã có comment nhưng bài post đã bị xóa mà chưa xóa comment (chưa ràng buộc khóa chính, khóa ngoại). Do đó, đây chỉ đơn giản là lấy ví dụ để minh họa RIGHT JOIN.