web-dev-qa-db-fra.com

Comment compter les lignes avec SELECT COUNT (*) avec SQLAlchemy?

Je voudrais savoir s'il est possible de générer une instruction SELECT COUNT(*) FROM TABLE dans SQLAlchemy sans la demander explicitement avec execute(). Si j'utilise:

session.query(table).count()

alors il génère quelque chose comme:

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

ce qui est beaucoup plus lent dans MySQL avec InnoDB. Je recherche une solution qui ne nécessite pas que la table ait une clé primaire connue, comme suggéré dans Obtenez le nombre de lignes dans la table en utilisant SQLAlchemy .

38
tiho

J'ai réussi à rendre le SELECT suivant avec SQLAlchemy sur les deux couches.

SELECT count(*) AS count_1
FROM "table"

Utilisation à partir de la couche d'expression 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)

Utilisation à partir de la couche ORM

Vous venez de sous-classe Query (vous avez probablement de toute façon) et fournissez une méthode spécialisée count(), comme celle-ci.

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()

Veuillez noter que order_by(None) réinitialise l'ordre de la requête, ce qui n'est pas pertinent pour le comptage.

En utilisant cette méthode, vous pouvez avoir une count(*) sur n'importe quelle requête ORM, qui honorera toutes les conditions filter et join déjà spécifiées.

52
pi.

Recherchez une seule colonne connue:

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

J'avais besoin de compter une requête très complexe avec de nombreuses jointures. J'utilisais les jointures comme filtres, donc je voulais seulement connaître le nombre d'objets réels. count () était insuffisant, mais j'ai trouvé la réponse dans les documents ici:

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

Le code ressemblerait à ceci (pour compter les objets utilisateur):

from sqlalchemy import func

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

Si vous utilisez l'approche SQL Expression Style, il existe une autre façon de construire l'instruction count si vous avez déjà votre objet table.

Préparations pour obtenir l'objet table. Il existe également différentes manières.

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                    

Emission de la requête de comptage sur le 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