Как подсчитать строки с помощью SELECT COUNT (*) с помощью SQLAlchemy?
Я хотел бы знать, возможно ли сгенерировать оператор SELECT COUNT(*) FROM TABLE
в SQLAlchemy без явного запроса его с помощью execute()
.
Если я использую:
session.query(table).count()
то он генерирует что-то вроде:
SELECT count(*) AS count_1 FROM
(SELECT table.col1 as col1, table.col2 as col2, ... from table)
который значительно медленнее в MySQL с InnoDB. Я ищу решение, которое не требует, чтобы таблица имела известный первичный ключ, как предложено в Получить количество строк в таблице, используя SQLAlchemy.
Ответы
Ответ 1
Мне удалось отобразить следующий SELECT с SQLAlchemy на обоих уровнях.
SELECT count(*) AS count_1
FROM "table"
Использование уровня SQL Expression
from sqlalchemy import select, func, Integer, Table, Column, MetaData
metadata = MetaData()
table = Table("table", metadata,
Column('primary_key', Integer),
Column('other_column', Integer) # just to illustrate
)
print select([func.count()]).select_from(table)
Использование с уровня ORM
Вы просто подклассом Query
(возможно, вы все равно) и предоставляете специализированный метод count()
, например этот.
from sqlalchemy import func
class BaseQuery(Query):
def count_star(self):
count_query = (self.statement.with_only_columns([func.count()])
.order_by(None))
return self.session.execute(count_query).scalar()
Обратите внимание, что order_by(None)
сбрасывает порядок запроса, что не имеет отношения к счету.
Используя этот метод, вы можете иметь count(*)
в любом запросе ORM, который будет соблюдать все уже указанные условия filter
и join
.
Ответ 2
Запрос только для одного известного столбца:
session.query(MyTable.col1).count()
Ответ 3
Мне нужно было сделать счет очень сложного запроса со многими объединениями. Я использовал соединения в качестве фильтров, поэтому мне хотелось узнать только количество фактических объектов. count() было недостаточно, но я нашел ответ в документах здесь:
http://docs.sqlalchemy.org/en/latest/orm/tutorial.html
Код будет выглядеть примерно так (для подсчета объектов пользователя):
from sqlalchemy import func
session.query(func.count(User.id)).scalar()
Ответ 4
Если вы используете подход SQL Expression Style, есть другой способ создать оператор count, если у вас уже есть объект таблицы.
Подготовка к получению табличного объекта. Есть и разные способы.
import sqlalchemy
database_engine = sqlalchemy.create_engine("connection string")
# Populate existing database via reflection into sqlalchemy objects
database_metadata = sqlalchemy.MetaData()
database_metadata.reflect(bind=database_engine)
table_object = database_metadata.tables.get("table_name") # This is just for illustration how to get the table_object
Выдача запроса на подсчет для table_object
query = table_object.count()
# This will produce something like, where id is a primary key column in "table_name" automatically selected by sqlalchemy
# 'SELECT count(table_name.id) AS tbl_row_count FROM table_name'
count_result = database_engine.scalar(query)