SQLAlchemy ORM - Bekerja dengan Gabungan

Sekarang kita memiliki dua tabel, kita akan melihat bagaimana membuat query pada kedua tabel secara bersamaan. Untuk membuat gabungan implisit sederhana antara Pelanggan dan Faktur, kita bisa menggunakan Query.filter () untuk menyamakan kolom terkait. Di bawah ini, kami memuat entitas Pelanggan dan Faktur sekaligus menggunakan metode ini -

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))

Ekspresi SQL yang dipancarkan oleh SQLAlchemy adalah sebagai berikut -

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

Dan hasil dari baris kode diatas adalah sebagai berikut -

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

Sintaks SQL JOIN yang sebenarnya mudah dicapai menggunakan metode Query.join () sebagai berikut -

session.query(Customer).join(Invoice).filter(Invoice.amount == 8500).all()

Ekspresi SQL untuk join akan ditampilkan di konsol -

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 = ?

Kita dapat melakukan iterasi melalui hasil menggunakan for loop -

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)

Dengan 8500 sebagai parameter bind, output berikut ditampilkan -

4 Govind Kala 8 8500

Query.join () tahu cara menggabungkan antara tabel-tabel ini karena hanya ada satu kunci asing di antara mereka. Jika tidak ada kunci asing, atau lebih banyak kunci asing, Query.join () bekerja lebih baik ketika salah satu dari formulir berikut digunakan -

query.join (Faktur, id == Alamat.custid) kondisi eksplisit
query.join (Customer.invoices) tentukan hubungan dari kiri ke kanan
query.join (Invoice, Customer.invoices) sama, dengan target eksplisit
query.join ('invoices') sama, menggunakan string

Demikian pula fungsi outerjoin () tersedia untuk mencapai gabungan luar kiri.

query.outerjoin(Customer.invoices)

Metode subquery () menghasilkan ekspresi SQL yang mewakili pernyataan SELECT yang disematkan di dalam alias.

from sqlalchemy.sql import func

stmt = session.query(
   Invoice.custid, func.count('*').label('invoice_count')
).group_by(Invoice.custid).subquery()

Objek stmt akan berisi pernyataan SQL seperti di bawah ini -

SELECT invoices.custid, count(:count_1) AS invoice_count FROM invoices GROUP BY invoices.custid

Setelah kami memiliki pernyataan kami, itu berperilaku seperti konstruksi Tabel. Kolom pada pernyataan dapat diakses melalui atribut yang disebut c seperti yang ditunjukkan pada kode di bawah ini -

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)

Perulangan for di atas menampilkan jumlah faktur berdasarkan nama sebagai berikut -

Arjun Pandit None
Gopal Krishna 2
Govind Pant 2
Govind Kala 2
Abdul Rahman 2