Метод distinct класса Select
Метод distinct класса Select
добавляет в SQL-запрос оператор DISTINCT,
который удаляет дублирующиеся строки из результата
выборки. Метод не принимает обязательных параметров
и возвращает новый объект Select, поэтому
его удобно использовать в цепочке вызовов.
Если в выборке участвует несколько колонок, то уникальность определяется по всей совокупности значений этих колонок. То есть две строки считаются дубликатами только тогда, когда совпадают значения во всех выбранных колонках.
Синтаксис
select(...).distinct()
Пример
Давайте создадим таблицу articles,
заполним её данными с повторяющимися значениями
и выберем уникальные статусы без метода
distinct:
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
articles = Table(
'articles', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('status', String),
)
metadata.create_all(engine)
with engine.begin() as conn:
conn.execute(articles.insert(), [
{'title': 'article 1', 'status': 'draft'},
{'title': 'article 2', 'status': 'published'},
{'title': 'article 3', 'status': 'draft'},
{'title': 'article 4', 'status': 'published'},
])
stmt = select(articles.c.status)
res = conn.execute(stmt).fetchall()
print(res)
Результат выполнения кода:
[('draft',), ('published',), ('draft',), ('published',)]
Пример
Теперь применим метод distinct,
чтобы получить только уникальные статусы:
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
articles = Table(
'articles', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('status', String),
)
metadata.create_all(engine)
with engine.begin() as conn:
conn.execute(articles.insert(), [
{'title': 'article 1', 'status': 'draft'},
{'title': 'article 2', 'status': 'published'},
{'title': 'article 3', 'status': 'draft'},
{'title': 'article 4', 'status': 'published'},
])
stmt = select(articles.c.status).distinct()
res = conn.execute(stmt).fetchall()
print(res)
Результат выполнения кода:
[('draft',), ('published',)]
Пример
Давайте посмотрим, какой SQL-запрос формирует
метод distinct:
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
articles = Table(
'articles', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('status', String),
)
stmt = select(articles.c.status).distinct()
print(stmt)
Итоговый SQL запрос:
SELECT DISTINCT articles.status
FROM articles
Пример
При выборке нескольких колонок уникальность
определяется по их совокупности. Давайте выберем
пары title и status с методом
distinct:
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
articles = Table(
'articles', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('status', String),
)
metadata.create_all(engine)
with engine.begin() as conn:
conn.execute(articles.insert(), [
{'title': 'article 1', 'status': 'draft'},
{'title': 'article 1', 'status': 'draft'},
{'title': 'article 2', 'status': 'draft'},
{'title': 'article 2', 'status': 'published'},
])
stmt = select(articles.c.title, articles.c.status).distinct()
res = conn.execute(stmt).fetchall()
print(res)
Результат выполнения кода:
[('article 1', 'draft'), ('article 2', 'draft'), ('article 2', 'published')]
Пример
Метод distinct возвращает новый объект
Select, поэтому его можно комбинировать
с другими методами, например с order_by:
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String, select
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
articles = Table(
'articles', metadata,
Column('id', Integer, primary_key=True),
Column('title', String),
Column('status', String),
)
metadata.create_all(engine)
with engine.begin() as conn:
conn.execute(articles.insert(), [
{'title': 'article 1', 'status': 'published'},
{'title': 'article 2', 'status': 'draft'},
{'title': 'article 3', 'status': 'published'},
{'title': 'article 4', 'status': 'draft'},
])
stmt = (
select(articles.c.status)
.distinct()
.order_by(articles.c.status)
)
res = conn.execute(stmt).fetchall()
print(res)
Результат выполнения кода:
[('draft',), ('published',)]