Метод outerjoin
Метод outerjoin класса Query выполняет
левое внешнее соединение (LEFT OUTER JOIN) основной
сущности запроса с указанной целью. Первым параметром
методу передается целевая сущность или условие ON.
В отличие от метода join, внешнее соединение
включает в результат строки основной таблицы, для
которых не нашлось совпадений в присоединяемой таблице.
Синтаксис
Query.outerjoin(target, [onclause], [full])
Пример
Давайте создадим две связанные модели и выполним внешнее соединение между ними:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(id=1, name='user')
session.add(user)
session.commit()
res = session.query(User).outerjoin(Article, User.id == Article.user_id).all()
print(res)
Результат выполнения кода:
[<__main__.User object at 0x...>]
Пример
Давайте посмотрим, какой SQL-запрос генерирует метод
outerjoin при явном указании условия ON:
from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int]
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
query = session.query(User).outerjoin(Article, User.id == Article.user_id)
print(query)
Итоговый SQL запрос:
SELECT users.id AS users_id, users.name AS users_name
FROM users LEFT OUTER JOIN articles ON users.id = articles.user_id
Пример
Давайте выполним внешнее соединение с использованием
связи между моделями через relationship:
from sqlalchemy import create_engine, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, Session
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
articles: Mapped[list['Article']] = relationship(back_populates='user')
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
user_id: Mapped[int] = mapped_column(ForeignKey('users.id'))
user: Mapped['User'] = relationship(back_populates='articles')
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
user = User(id=1, name='user')
session.add(user)
session.commit()
res = session.query(User).outerjoin(User.articles).all()
print(res)
Результат выполнения кода:
[<__main__.User object at 0x...>]