101 votes

Obtenir une ligne aléatoire par SQLAlchemy

Comment sélectionner une ou plusieurs lignes aléatoires dans un tableau à l'aide de SQLAlchemy ?

158voto

Łukasz Points 5614

Il s'agit d'une question très spécifique à la base de données.

Je sais que PostgreSQL, SQLite, MySQL et Oracle ont la possibilité d'ordonner par une fonction aléatoire, vous pouvez donc l'utiliser dans SQLAlchemy :

from  sqlalchemy.sql.expression import func, select

select.order_by(func.random()) # for PostgreSQL, SQLite

select.order_by(func.rand()) # for MySQL

select.order_by('dbms_random.value') # For Oracle

Ensuite, vous devez limiter la requête en fonction du nombre d'enregistrements dont vous avez besoin (par exemple en utilisant .limit() ).

Gardez à l'esprit qu'au moins dans PostgreSQL, la sélection d'un enregistrement aléatoire pose de sérieux problèmes de performance ; aquí est un bon article à ce sujet.

14 votes

+1. La même chose que Postgres fonctionne pour SQLite : select.order_by(func.random()).limit(n)

0 votes

Vous pouvez utiliser order_by('dbms_random.value') dans Oracle.

0 votes

J'ai ajouté l'import du mieux que je peux sans que SQLAlchemy soit installé - quelqu'un peut-il confirmer que c'est bien le cas ? J'ai également modifié les suggestions de Bernie et de Buttons840 dans la réponse.

27voto

David Raznick Points 5074

Si vous utilisez l'orm et que la table n'est pas grande (ou que vous avez son nombre de lignes en cache) et que vous voulez qu'elle soit indépendante de la base de données, l'approche la plus simple est la suivante.

import random
rand = random.randrange(0, session.query(Table).count()) 
row = session.query(Table)[rand]

C'est un peu de la triche, mais c'est pour cela qu'on utilise un orme.

0 votes

Rand = random.randrange(0, session.query(Table).count())

0 votes

Vous sélectionnez et créez tous les objets avant de choisir l'une des options suivantes

0 votes

Pourquoi pas random.choice(session.query(Table)) ?

23voto

GuySoft Points 313

Il existe un moyen simple de tirer une ligne aléatoire qui EST indépendant de la base de données. Il suffit d'utiliser .offset() . Il n'est pas nécessaire d'extraire toutes les lignes :

import random
query = DBSession.query(Table)
rowCount = int(query.count())
randomRow = query.offset(int(rowCount*random.random())).first()

Où Table est votre table (ou vous pouvez y placer n'importe quelle requête). Si vous souhaitez obtenir quelques lignes, vous pouvez exécuter cette requête plusieurs fois et vous assurer que chaque ligne n'est pas identique à la précédente.

0 votes

Mise à jour - à environ 10 millions de lignes dans mysql, cela a commencé à devenir un peu lent, je suppose que vous pourriez l'optimiser.

1 votes

Cela fonctionne bien pour moi dans un cadre de 500 000 rangs environ.

1 votes

Maintenant à 11 millions de lignes sur Oracle...., ce n'est plus aussi bien :-) Dégradation linéaire, mais quand même... Je dois trouver autre chose.

-2voto

dalloliogm Points 2628

Une version améliorée de l'exemple de Lukasz, dans le cas où vous devez sélectionner plusieurs lignes au hasard :

import random

# you must first select all the values of the primary key field for the table.
# in some particular cases you can use xrange(session.query(Table).count()) instead
ids = session.query(Table.primary_key_field).all() 
ids_sample = random.sample(ids, 100)

rows = session.query(Table).filter(Table.primary_key_field.in_(ids_sample))

Ce billet a donc pour but de souligner que vous pouvez utiliser .in_ pour sélectionner plusieurs champs en même temps.

-3voto

med116 Points 30

Cette solution sélectionnera une seule ligne aléatoire

Cette solution nécessite que la clé primaire soit nommée id, elle devrait l'être si ce n'est pas déjà le cas :

import random
max_model_id = YourModel.query.order_by(YourModel.id.desc())[0].id
random_id = random.randrange(0,max_model_id)
random_row = YourModel.query.get(random_id)
print random_row

5 votes

Cette méthode échoue lorsqu'il y a une lacune dans les identifiants.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X