Bonjour,

Pourriez-vous m'indiquer comment je peux faire pour afficher 50 résultats de la requête suivante au lieu d'un seul ? J'aimerais le faire directement dans la requête SQL et non pas passer par une boucle For en répétant 50 fois la requête.

La requête SQL :

SELECT name 
FROM words 
JOIN(
    SELECT FLOOR( COUNT( * ) * RAND( ) ) 
    AS random FROM words
     ) 
AS V ON words.id = V.random


Merci d'avance pour votre aide !
Smiley cligne
Modifié par flox (01 Jun 2017 - 12:11)
Bonjour.

Il y a plus de 50 'names' dans 'words' et vous voulez que tous les résultats soient différents ? Dans ce cas, pourquoi ne pas les trier aléatoirement (SQL RAND()) et prendre les cinquante premiers :
SELECT name
FROM words
ORDER BY RAND()
LIMIT 50;


Smiley smile
Bonsoir,

Attention au fait que order by rand() devient rapidement très lent si la table est volumineuse.
Au-delà de quelques milliers d'enregistrements déjà, ce n'est plus trop recommandé.

Dans ce cas, le plus simple sera sans doute de le faire en trois temps:
1. select count(*) from words
2. Utiliser un langage serveur pour générer 50 nombres pseudo-aléatoires entre 1 et count(*) (PHP, python, Java, etc.)
3. select name from words where id in(...)

Inconvénient: on suppose que les id sont continus, i.e. qu'il n'y a pas de trous. Si on doit prendre en compte les trous, soit la requête va se complexifier notablement, soit il faut faire de la réattribution d'id à la suppression (ce qui peut rapidement être source d'autres problèmes, dont la consistance des références dans le temps)

Avantage: c'est très simple et très rapide

Deuxième solution possible:
Etape de préparation à faire une seule fois:
1. Ajouter une nouvelle colonne, p.ex. randomValue, de type double: alter table words add randomValue double
2. update words set randomValue = rand()
ET pour sélectionner 50 éléments ensuite, on peut procéder par exemple avec:
1. set @random := rand()
2. select name from words order by abs(randomValue-@random) asc limit 50
Gare à ne pas faire order by randomValue-rand() sinon on retombe dans le problème de lenteur

Inconvénient: selon la valeur attribuée à randomValue, toutes les lignes n'ont pas la même probabilité de sortir; les randomValue extrêmums (proches de 0 ou de 1) ont moins de chances, tout comme les randomValue les plus isolés (avec des voisins moins proches) ont plus de chances.
Des systèmes plus ou moins élaborés, réattribuant une nouvelle valeur randomValue aux éléments qui sont sortis, ou une redistribution périodique tous les jours à minuit par exemple, n'ont guère de chance d'augmenter l'équiprobabilité.
A moins que randomValue soit indexée, ça nécéssite un parcours complet de la table, donc ce sera un peu plus lent que de piocher des id

Avantage: tu peux étendre cette solution pour faire un système où tous les éléments doivent avoir été tirés une fois avant de pouvoir être à nouveau tirés une deuxième fois, ce serait alors un aléatoire préparé à l'avance, semblable au bouton shuffle sur les lecteurs de musique. pour cela:
1. On ajoute une colonne compteur: alter words add drawnCount int default 0
2. ET à la sélection: select name from words order by drawnCount asc, randomValue asc limit 50; suivi de update words set drawnCount = drawnCount +1 order by drawCount asc, randomValue asc; pour mettre à jour les lignes qui ont été tirées.

Voilà, j'espère que tu trouveras ton bonheur dans cette réponse. Tirer des lignes au hasard dans une table n'est pas si facile qu'il n'y paraît.
Meilleure solution
Bonsoir,

En effet la base est très volumineuse (22000 noms) donc la solution de Zelena rendrait le traitement trop long.

Tes propositions sont toutes très intéressantes QuentinC et je pense que je vais partir sur la première en procédant avec du PHP.
Merci à vous deux.

Bonne soirée.