[英]How to count rows with SELECT COUNT(*) with SQLAlchemy?
I'd like to know if it's possible to generate a SELECT COUNT(*) FROM TABLE
statement in SQLAlchemy without explicitly asking for it with execute()
.我想知道是否可以在 SQLAlchemy 中生成
SELECT COUNT(*) FROM TABLE
语句,而无需使用execute()
明确要求它。 If I use:如果我使用:
session.query(table).count()
then it generates something like:然后它会生成如下内容:
SELECT count(*) AS count_1 FROM
(SELECT table.col1 as col1, table.col2 as col2, ... from table)
which is significantly slower in MySQL with InnoDB.使用 InnoDB 在 MySQL 中速度明显较慢。 I am looking for a solution that doesn't require the table to have a known primary key, as suggested in Get the number of rows in table using SQLAlchemy .
我正在寻找一种不需要表具有已知主键的解决方案,如使用 SQLAlchemy 获取表中的行数中所建议的那样。
仅查询单个已知列:
session.query(MyTable.col1).count()
I managed to render the following SELECT with SQLAlchemy on both layers.我设法在两个层上使用 SQLAlchemy 呈现以下 SELECT。
SELECT count(*) AS count_1
FROM "table"
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)
You just subclass Query
(you have probably anyway) and provide a specialized count()
method, like this one.您只需将
Query
子类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()
Please note that order_by(None)
resets the ordering of the query, which is irrelevant to the counting.请注意
order_by(None)
重置查询的顺序,这与计数无关。
Using this method you can have a count(*)
on any ORM Query, that will honor all the filter
and join
conditions already specified.使用此方法,您可以在任何 ORM 查询上使用
count(*)
,这将遵守所有已指定的filter
和join
条件。
I needed to do a count of a very complex query with many joins.我需要对具有许多连接的非常复杂的查询进行计数。 I was using the joins as filters, so I only wanted to know the count of the actual objects.
我使用连接作为过滤器,所以我只想知道实际对象的数量。 count() was insufficient, but I found the answer in the docs here:
count() 是不够的,但我在这里的文档中找到了答案:
http://docs.sqlalchemy.org/en/latest/orm/tutorial.html http://docs.sqlalchemy.org/en/latest/orm/tutorial.html
The code would look something like this (to count user objects):代码看起来像这样(计算用户对象):
from sqlalchemy import func
session.query(func.count(User.id)).scalar()
Addition to the Usage from the ORM layer in the accepted answer: count(*) can be done for ORM using the query.with_entities(func.count())
, like this:在接受的答案中添加来自 ORM 层的Usage :count(*) 可以使用
query.with_entities(func.count())
为 ORM 完成,如下所示:
session.query(MyModel).with_entities(func.count()).scalar()
It can also be used in more complex cases, when we have joins and filters - the important thing here is to place with_entities
after joins, otherwise SQLAlchemy could raise the Don't know how to join
error.它也可以用于更复杂的情况,当我们有连接和过滤器时——这里重要的是在连接之后放置
with_entities
,否则 SQLAlchemy 可能会引发Don't know how to join
错误。
For example:例如:
User
model ( id
, name
) and Song
model ( id
, title
, genre
)User
模型( id
, name
)和Song
模型( id
, title
, genre
)UserSong
model ( user_id
, song_id
, is_liked
) where user_id
+ song_id
is a primary key)UserSong
模型( user_id
, song_id
, is_liked
),其中user_id
+ song_id
是主键) We want to get a number of user's liked rock songs:我们想要获得一些用户喜欢的摇滚歌曲:
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'
This query can be generated in a following way:此查询可以通过以下方式生成:
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()
If you are using the SQL Expression Style approach there is another way to construct the count statement if you already have your table object.如果您正在使用 SQL 表达式样式方法,如果您已经拥有表对象,则还有另一种方法来构造计数语句。
Preparations to get the table object.准备获取表对象。 There are also different ways.
也有不同的方式。
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
Issuing the count query on 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)
I'm not clear on what you mean by "without explicitly asking for it with execute()" So this might be exactly what you are not asking for.我不清楚您所说的“没有使用execute()明确要求”是什么意思所以这可能正是您不要求的。 OTOH, this might help others.
OTOH,这可能对其他人有所帮助。
You can just run the textual SQL:您可以只运行文本 SQL:
your_query="""
SELECT count(*) from table
"""
the_count = session.execute(text(your_query)).scalar()
Below is the way to find the count of any query.以下是查找任何查询计数的方法。
aliased_query = alias(query)
db.session.query(func.count('*')).select_from(aliased_query).scalar()
Here is the link to the reference document if you want to explore more options or read details.如果您想探索更多选项或阅读详细信息,请访问参考文档的链接。
def test_query(val: str):
query = f"select count(*) from table where col1='{val}'"
rtn = database_engine.query(query)
cnt = rtn.one().count
but you can find the way if you checked debug watch但是如果您检查了调试手表,您可以找到方法
query = session.query(table.column).filter().with_entities(func.count(table.column.distinct())) count = query.scalar()查询 = session.query(table.column).filter().with_entities(func.count(table.column.distinct())) count = query.scalar()
this worked for me.这对我有用。
Gives the query: SELECT count(DISTINCT table.column) AS count_1 FROM table where...给出查询:SELECT count(DISTINCT table.column) AS count_1 FROM table where...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.