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