SQLAlchemy ORM - ทำงานร่วมกับ Joins

ตอนนี้เรามีสองตารางแล้วเราจะดูวิธีสร้างแบบสอบถามบนทั้งสองตารางในเวลาเดียวกัน ในการสร้างการรวมโดยนัยอย่างง่ายระหว่างลูกค้าและใบแจ้งหนี้เราสามารถใช้ Query.filter () เพื่อนำคอลัมน์ที่เกี่ยวข้องมารวมกัน ด้านล่างนี้เราโหลดเอนทิตีลูกค้าและใบแจ้งหนี้พร้อมกันโดยใช้วิธีนี้ -

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

นิพจน์ SQL ที่ปล่อยออกมาโดย SQLAlchemy มีดังนี้ -

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

และผลลัพธ์ของบรรทัดข้างต้นของโค้ดมีดังนี้ -

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

ไวยากรณ์ของ SQL JOIN จริงสามารถทำได้อย่างง่ายดายโดยใช้เมธอด Query.join () ดังต่อไปนี้ -

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

นิพจน์ SQL สำหรับการเข้าร่วมจะแสดงบนคอนโซล -

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

เราสามารถวนซ้ำผลลัพธ์โดยใช้ 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)

ด้วย 8500 เป็นพารามิเตอร์การผูกเอาต์พุตต่อไปนี้จะปรากฏขึ้น -

4 Govind Kala 8 8500

Query.join () รู้วิธีเข้าร่วมระหว่างตารางเหล่านี้เนื่องจากมีคีย์ต่างประเทศเพียงหนึ่งคีย์ระหว่างกัน หากไม่มีคีย์ต่างประเทศหรือคีย์ต่างประเทศมากกว่า Query.join () จะทำงานได้ดีขึ้นเมื่อใช้รูปแบบใดรูปแบบหนึ่งต่อไปนี้ -

query.join (ใบแจ้งหนี้ id == Address.custid) เงื่อนไขที่ชัดเจน
query.join (Customer.invoices) ระบุความสัมพันธ์จากซ้ายไปขวา
query.join (ใบแจ้งหนี้ Customer.invoices) เหมือนกันกับเป้าหมายที่ชัดเจน
query.join ('ใบแจ้งหนี้') เหมือนกันโดยใช้สตริง

ฟังก์ชัน outerjoin () ในทำนองเดียวกันพร้อมใช้งานเพื่อให้ได้การรวมภายนอกด้านซ้าย

query.outerjoin(Customer.invoices)

subquery () method สร้างนิพจน์ SQL ที่แสดงคำสั่ง SELECT ที่ฝังอยู่ภายในนามแฝง

from sqlalchemy.sql import func

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

วัตถุ stmt จะมีคำสั่ง SQL ดังต่อไปนี้ -

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

เมื่อเรามีคำสั่งของเรามันจะทำงานเหมือนการสร้างตาราง คอลัมน์ในคำสั่งสามารถเข้าถึงได้ผ่านแอตทริบิวต์ที่เรียกว่า c ดังที่แสดงในโค้ดด้านล่าง -

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)

ด้านบนสำหรับการวนรอบแสดงจำนวนใบแจ้งหนี้ตามชื่อดังนี้ -

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