Теперь, когда у нас есть две таблицы, мы увидим, как создавать запросы для обеих таблиц одновременно. Чтобы создать простое неявное соединение между Customer и Invoice, мы можем использовать Query.filter (), чтобы приравнять их связанные столбцы. Ниже мы сразу загружаем объекты Customer и Invoice, используя этот метод —
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 —
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 (Invoice, Customer.invoices) | то же самое, с явной целью |
query.join ( ‘счета’) | то же самое, используя строку |
Точно так же функция externaljoin () доступна для достижения внешнего левого соединения.
query.outerjoin(Customer.invoices)
Метод subquery () создает выражение 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)
Вышеуказанный цикл for отображает количество счетов по именам следующим образом: