如何使用SQLAlchemy使用SELECT COUNT(*)计算行数?

时间:2012-10-17 18:59:49

标签: python sql sqlalchemy

我想知道是否可以在SQLAlchemy中生成SELECT COUNT(*) FROM TABLE语句而不用execute()明确要求它。 如果我使用:

session.query(table).count()

然后它会产生类似的东西:

SELECT count(*) AS count_1 FROM
    (SELECT table.col1 as col1, table.col2 as col2, ... from table)

使用InnoDB在MySQL中明显变慢。我正在寻找一种解决方案,该解决方案并不要求表格具有已知的主键,如Get the number of rows in table using SQLAlchemy中所述。

6 个答案:

答案 0 :(得分:50)

我设法在两个图层上使用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 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(*),以符合已指定的所有filterjoin条件。

答案 1 :(得分:36)

仅查询单个已知列:

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

答案 2 :(得分:19)

我需要计算一个包含许多连接的非常复杂的查询。我使用连接作为过滤器,所以我只想知道实际对象的数量。 count()不足,但我在文档中找到了答案:

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

代码看起来像这样(计算用户对象):

from sqlalchemy import func

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

答案 3 :(得分:2)

在接受的答案中添加到 ORM层的用法:可以使用query.with_entities(func.count())对ORM进行count(*),如下所示:

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

它也可以在更复杂的情况下使用,当我们有联接和过滤器时-重要的是在联接之后放置with_entities,否则SQLAlchemy可能会引发Don't know how to join错误。

例如:

  • 我们有User模型(idname)和Song模型(idtitlegenre
  • 我们有用户歌曲数据-UserSong模型(user_idsong_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()

完整的示例是here

答案 4 :(得分:1)

以下是查找任何查询计数的方法。

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

如果您想探索更多选项或阅读详细信息,请点击 link to the reference document

答案 5 :(得分:0)

如果您使用的是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)