SQLAlchemy ORM - Arbeiten mit Joins

Nachdem wir nun zwei Tabellen haben, werden wir sehen, wie Abfragen für beide Tabellen gleichzeitig erstellt werden. Um eine einfache implizite Verknüpfung zwischen Kunde und Rechnung zu erstellen, können wir Query.filter () verwenden, um die zugehörigen Spalten miteinander gleichzusetzen. Im Folgenden laden wir die Kunden- und Rechnungsentitäten mit dieser Methode sofort -

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

Der von SQLAlchemy ausgegebene SQL-Ausdruck lautet wie folgt:

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

Und das Ergebnis der obigen Codezeilen ist wie folgt:

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

Die eigentliche SQL JOIN-Syntax kann mit der Query.join () -Methode wie folgt erreicht werden:

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

Der SQL-Ausdruck für den Join wird auf der Konsole angezeigt.

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

Wir können das Ergebnis mit for loop durchlaufen -

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)

Mit 8500 als Bindungsparameter wird die folgende Ausgabe angezeigt:

4 Govind Kala 8 8500

Query.join () kann zwischen diesen Tabellen verknüpfen, da sich nur ein Fremdschlüssel zwischen ihnen befindet. Wenn keine oder mehrere Fremdschlüssel vorhanden waren, funktioniert Query.join () besser, wenn eines der folgenden Formulare verwendet wird:

query.join (Rechnung, id == Address.custid) explizite Bedingung
query.join (Customer.invoices) Geben Sie die Beziehung von links nach rechts an
query.join (Rechnung, Kundenrechnungen) Gleiches gilt für das explizite Ziel
query.join ('Rechnungen') das gleiche, mit einem String

In ähnlicher Weise ist die Funktion Outerjoin () verfügbar, um eine Linksaußenverknüpfung zu erreichen.

query.outerjoin(Customer.invoices)

Die Methode subquery () erzeugt einen SQL-Ausdruck, der die in einen Alias ​​eingebettete SELECT-Anweisung darstellt.

from sqlalchemy.sql import func

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

Das stmt-Objekt enthält eine SQL-Anweisung wie folgt:

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

Sobald wir unsere Anweisung haben, verhält sie sich wie ein Tabellenkonstrukt. Auf die Spalten in der Anweisung kann über ein Attribut namens c zugegriffen werden, wie im folgenden Code gezeigt.

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)

Die obige for-Schleife zeigt die Anzahl der Rechnungen wie folgt an:

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