Метод outerjoin
Метод outerjoin класса Select выполняет
левое внешнее соединение (LEFT OUTER JOIN) таблиц.
Первым параметром метод принимает целевую таблицу
или модель для соединения. В отличие от join,
который выполняет внутреннее соединение, outerjoin
сохраняет все строки левой таблицы, даже если для них
нет совпадений в правой таблице. Необязательным вторым
параметром передается условие соединения onclause.
Синтаксис
select(...).outerjoin(target, [onclause])
Пример
Давайте создадим две модели и выполним левое внешнее
соединение. Модель User имеет поле article_id,
которое ссылается на статью. Даже если у пользователя
нет статьи, он останется в результатах:
from sqlalchemy import create_engine, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'), nullable=True)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(id=1, title='article')
user1 = User(id=1, name='user1', article_id=1)
user2 = User(id=2, name='user2', article_id=None)
session.add_all([article, user1, user2])
session.commit()
stmt = select(User.name, Article.title).outerjoin(Article, User.article_id == Article.id)
res = session.execute(stmt).all()
print(res)
Результат выполнения кода:
[('user1', 'article'), ('user2', None)]
Пример
Давайте посмотрим итоговый SQL-запрос, который
генерирует метод outerjoin:
from sqlalchemy import create_engine, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'), nullable=True)
stmt = select(User.name, Article.title).outerjoin(Article, User.article_id == Article.id)
print(stmt)
Итоговый SQL запрос:
SELECT users.name, articles.title
FROM users LEFT OUTER JOIN articles ON users.article_id = articles.id
Пример
Давайте выполним цепочку соединений, где одно из них внешнее. Сначала присоединим таблицу статей, а затем внешним соединением добавим пользователей:
from sqlalchemy import create_engine, ForeignKey, select
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
class User(Base):
__tablename__ = 'users'
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
article_id: Mapped[int] = mapped_column(ForeignKey('articles.id'), nullable=True)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine) as session:
article = Article(id=1, title='article')
user1 = User(id=1, name='user1', article_id=1)
user2 = User(id=2, name='user2', article_id=None)
session.add_all([article, user1, user2])
session.commit()
stmt = select(User.name, Article.title).outerjoin(Article)
res = session.execute(stmt).all()
print(res)
Результат выполнения кода:
[('user1', 'article'), ('user2', None)]