web-dev-qa-db-ja.com

SQLAlchemyでSELECT COUNT(*)を使用して行をカウントする方法は?

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)

innoDBを使用するMySQLでは大幅に遅くなります。 SQLAlchemyを使用してテーブル内の行数を取得する で提案されているように、テーブルに既知の主キーを必要としないソリューションを探しています。

38
tiho

両方のレイヤーでSQLAlchemyを使用して次のSELECTをレンダリングできました。

_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)はクエリの順序をリセットすることに注意してください。これはカウントとは無関係です。

このメソッドを使用すると、ORMクエリでcount(*)を使用できます。これにより、既に指定されているすべてのfilterおよびjoin条件が尊重されます。

52
pi.

既知の単一の列のみを照会します。

session.query(MyTable.col1).count()
37

多くの結合を伴う非常に複雑なクエリを数える必要がありました。結合をフィルターとして使用していたため、実際のオブジェクトの数だけを知りたいと思いました。 count()は不十分でしたが、私はここのドキュメントで答えを見つけました:

http://docs.sqlalchemy.org/en/latest/orm/tutorial.html

コードは次のようになります(ユーザーオブジェクトをカウントするため)。

from sqlalchemy import func

session.query(func.count(User.id)).scalar() 
19
melchoir55

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)
0
Ole