SQLAlchemy ORM - Làm việc với Joins
Bây giờ chúng ta có hai bảng, chúng ta sẽ xem cách tạo truy vấn trên cả hai bảng cùng một lúc. Để tạo một liên kết ngầm đơn giản giữa Khách hàng và Hóa đơn, chúng ta có thể sử dụng Query.filter () để cân bằng các cột liên quan của chúng với nhau. Dưới đây, chúng tôi tải các thực thể Khách hàng và Hóa đơn cùng một lúc bằng phương pháp này -
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
for c, i in session.query(Customer, Invoice).filter(Customer.id == Invoice.custid).all():
print ("ID: {} Name: {} Invoice No: {} Amount: {}".format(c.id,c.name, i.invno, i.amount))
Biểu thức SQL do SQLAlchemy phát ra như sau:
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email, invoices.id
AS invoices_id, invoices.custid
AS invoices_custid, invoices.invno
AS invoices_invno, invoices.amount
AS invoices_amount
FROM customers, invoices
WHERE customers.id = invoices.custid
Và kết quả của các dòng mã trên như sau:
ID: 2 Name: Gopal Krishna Invoice No: 10 Amount: 15000
ID: 2 Name: Gopal Krishna Invoice No: 14 Amount: 3850
ID: 3 Name: Govind Pant Invoice No: 3 Amount: 10000
ID: 3 Name: Govind Pant Invoice No: 4 Amount: 5000
ID: 4 Name: Govind Kala Invoice No: 7 Amount: 12000
ID: 4 Name: Govind Kala Invoice No: 8 Amount: 8500
ID: 5 Name: Abdul Rahman Invoice No: 9 Amount: 15000
ID: 5 Name: Abdul Rahman Invoice No: 11 Amount: 6000
Cú pháp SQL JOIN thực tế có thể dễ dàng đạt được bằng cách sử dụng phương thức Query.join () như sau:
session.query(Customer).join(Invoice).filter(Invoice.amount == 8500).all()
Biểu thức SQL cho phép nối sẽ được hiển thị trên bảng điều khiển -
SELECT customers.id
AS customers_id, customers.name
AS customers_name, customers.address
AS customers_address, customers.email
AS customers_email
FROM customers JOIN invoices ON customers.id = invoices.custid
WHERE invoices.amount = ?
Chúng ta có thể lặp lại kết quả bằng vòng lặp for -
result = session.query(Customer).join(Invoice).filter(Invoice.amount == 8500)
for row in result:
for inv in row.invoices:
print (row.id, row.name, inv.invno, inv.amount)
Với 8500 là tham số liên kết, kết quả sau được hiển thị:
4 Govind Kala 8 8500
Query.join () biết cách nối giữa các bảng này vì chỉ có một khóa ngoại giữa chúng. Nếu không có khóa ngoại hoặc nhiều khóa ngoại hơn, Query.join () sẽ hoạt động tốt hơn khi một trong các dạng sau được sử dụng:
query.join (Hóa đơn, id == Address.custid) | điều kiện rõ ràng |
query.join (Customer.invoices) | xác định mối quan hệ từ trái sang phải |
query.join (Hóa đơn, Khách hàng.invoices) | giống nhau, với mục tiêu rõ ràng |
query.join ('hóa đơn') | tương tự, sử dụng một chuỗi |
Tương tự như vậy, hàm ngoài () có sẵn để đạt được kết nối bên ngoài bên trái.
query.outerjoin(Customer.invoices)
Phương thức subquery () tạo ra một biểu thức SQL đại diện cho câu lệnh SELECT được nhúng trong một bí danh.
from sqlalchemy.sql import func
stmt = session.query(
Invoice.custid, func.count('*').label('invoice_count')
).group_by(Invoice.custid).subquery()
Đối tượng stmt sẽ chứa một câu lệnh SQL như sau:
SELECT invoices.custid, count(:count_1) AS invoice_count FROM invoices GROUP BY invoices.custid
Khi chúng ta có câu lệnh của mình, nó hoạt động giống như một cấu trúc Bảng. Các cột trên câu lệnh có thể truy cập được thông qua một thuộc tính được gọi là c như được hiển thị trong đoạn mã dưới đây:
for u, count in session.query(Customer, stmt.c.invoice_count).outerjoin(stmt, Customer.id == stmt.c.custid).order_by(Customer.id):
print(u.name, count)
Vòng lặp for ở trên hiển thị số lượng hóa đơn theo tên khôn ngoan như sau:
Arjun Pandit None
Gopal Krishna 2
Govind Pant 2
Govind Kala 2
Abdul Rahman 2