Comment sélectionner une ou plusieurs lignes aléatoires dans un tableau à l'aide de SQLAlchemy ?
+1. La même chose que Postgres fonctionne pour SQLite : select.order_by(func.random()).limit(n)
Comment sélectionner une ou plusieurs lignes aléatoires dans un tableau à l'aide de SQLAlchemy ?
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.
+1. La même chose que Postgres fonctionne pour SQLite : select.order_by(func.random()).limit(n)
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.
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.
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.
Mise à jour - à environ 10 millions de lignes dans mysql, cela a commencé à devenir un peu lent, je suppose que vous pourriez l'optimiser.
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.
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.
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
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.