РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
279 of 711 menu

Метод having класса Query

Метод having класса Query добавляет условие HAVING к SQL-запросу. Он применяется после группировки group_by и позволяет отфильтровать уже сгруппированные строки по агрегатным функциям, таким как count, sum, avg, max, min. Первым параметром метод принимает условие фильтрации, которое может быть выражением SQLAlchemy или текстовой строкой.

Синтаксис

query.having(criterion)

Пример

Давайте создадим модель Article и несколько записей для демонстрации работы метода:

from sqlalchemy import create_engine, String, Integer 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] = mapped_column(String(50)) text: Mapped[str] = mapped_column(String(200)) status: Mapped[str] = mapped_column(String(20)) num: Mapped[int] = mapped_column(Integer) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', text='text 1', status='draft', num=1), Article(title='article 2', text='text 2', status='draft', num=2), Article(title='article 3', text='text 3', status='published', num=3), Article(title='article 4', text='text 4', status='published', num=4), Article(title='article 5', text='text 5', status='published', num=5), ]) session.commit()

Пример

Давайте сгруппируем статьи по статусу и оставим только те группы, в которых больше двух статей:

from sqlalchemy import create_engine, String, Integer, func 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] = mapped_column(String(50)) text: Mapped[str] = mapped_column(String(200)) status: Mapped[str] = mapped_column(String(20)) num: Mapped[int] = mapped_column(Integer) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', text='text 1', status='draft', num=1), Article(title='article 2', text='text 2', status='draft', num=2), Article(title='article 3', text='text 3', status='published', num=3), Article(title='article 4', text='text 4', status='published', num=4), Article(title='article 5', text='text 5', status='published', num=5), ]) session.commit() res = session.query( Article.status, func.count(Article.id).label('cnt') ).group_by(Article.status).having(func.count(Article.id) > 2).all() print(res)

Результат выполнения кода:

[('published', 3)]

Пример

Давайте отфильтруем группы по максимальному значению поля num, оставив только те, где максимум больше трёх:

from sqlalchemy import create_engine, String, Integer, func 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] = mapped_column(String(50)) text: Mapped[str] = mapped_column(String(200)) status: Mapped[str] = mapped_column(String(20)) num: Mapped[int] = mapped_column(Integer) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: session.add_all([ Article(title='article 1', text='text 1', status='draft', num=1), Article(title='article 2', text='text 2', status='draft', num=2), Article(title='article 3', text='text 3', status='published', num=3), Article(title='article 4', text='text 4', status='published', num=4), Article(title='article 5', text='text 5', status='published', num=5), ]) session.commit() res = session.query( Article.status, func.max(Article.num).label('max_num') ).group_by(Article.status).having(func.max(Article.num) > 3).all() print(res)

Результат выполнения кода:

[('published', 5)]

Пример

Давайте посмотрим итоговый SQL-запрос, который генерирует метод having:

from sqlalchemy import create_engine, String, Integer, func 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] = mapped_column(String(50)) text: Mapped[str] = mapped_column(String(200)) status: Mapped[str] = mapped_column(String(20)) num: Mapped[int] = mapped_column(Integer) engine = create_engine('sqlite:///:memory:') Base.metadata.create_all(engine) with Session(engine) as session: query = session.query( Article.status, func.count(Article.id).label('cnt') ).group_by(Article.status).having(func.count(Article.id) > 2) print(query)

Итоговый SQL запрос:

SELECT articles.status AS articles_status, count(articles.id) AS cnt FROM articles GROUP BY articles.status HAVING count(articles.id) > ?

Смотрите также

  • метод group_by,
    который группирует строки по указанным колонкам
  • метод filter,
    который добавляет условие WHERE к запросу
  • метод count,
    который возвращает количество строк в результате
  • класс Query,
    который представляет ORM-запрос к базе данных
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить