85

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を使用してテーブルの行数を取得するで提案されているように、テーブルに既知の主キーが必要ないソリューションを探しています。

4

7 に答える 7

93

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

SELECT count(*) AS count_1
FROM "table"

SQL式レイヤーからの使用

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.sql.expression 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クエリを実行できます。filterjoin

于 2012-10-17T20:03:28.237 に答える
90

既知の列を1つだけクエリします。

session.query(MyTable.col1).count()
于 2012-10-17T19:56:13.183 に答える
28

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

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

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

from sqlalchemy import func

session.query(func.count(User.id)).scalar() 
于 2015-06-04T01:48:42.263 に答える
14

受け入れられた回答のORMレイヤーからの使用法への追加:count(*)はquery.with_entities(func.count())、次のように、を使用してORMに対して実行できます。

session.query(MyModel).with_entities(func.count()).scalar()

結合とフィルターがある場合、より複雑な場合にも使用できます。ここで重要なのはwith_entities、結合の後に配置することです。そうしないと、SQLAlchemyでDon't know how to joinエラーが発生する可能性があります。

例えば:

  • Userモデル(idname)とSongモデル(、、id)がありtitleますgenre
  • ユーザーソングデータがあります-UserSongモデル(user_id、、 ) song_idis_likedここでuser_id+song_idは主キーです)

ユーザーが気に入ったロックソングをいくつか入手したいと思います。

SELECT count(*) 
  FROM user_song
  JOIN song ON user_song.song_id = song.id 
 WHERE user_song.user_id = %(user_id)
   AND user_song.is_liked IS 1
   AND song.genre = 'rock'

このクエリは、次の方法で生成できます。

user_id = 1

query = session.query(UserSong)
query = query.join(Song, Song.id == UserSong.song_id)
query = query.filter(
    and_(
        UserSong.user_id == user_id, 
        UserSong.is_liked.is_(True),
        Song.genre == 'rock'
    )
)
# Note: important to place `with_entities` after the join
query = query.with_entities(func.count())
liked_count = query.scalar()

完全な例はここにあります。

于 2019-09-14T10:19:00.760 に答える
1

SQL式スタイルのアプローチを使用している場合、すでにテーブルオブジェクトがある場合は、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)
于 2019-07-03T08:31:21.963 に答える
0

「execute()で明示的に要求しない」とはどういう意味かわかりません。したがって、これはまさにあなたが要求していないことかもしれません。OTOH、これは他の人を助けるかもしれません。

テキストSQLを実行するだけです。

your_query="""
SELECT count(*) from table
"""
the_count = session.execute(text(your_query)).scalar()
于 2022-02-09T21:10:43.357 に答える
-1

以下は、クエリの数を見つける方法です。

aliased_query = alias(query)
db.session.query(func.count('*')).select_from(aliased_query).scalar()

その他のオプションを調べたり、詳細を読みたい場合は、リファレンスドキュメントへのリンクを次に示します。

于 2021-03-08T07:57:24.693 に答える