Moche, mais rapide et aléatoire. Peut devenir très moche très vite, surtout avec le réglage décrit ci-dessous, alors assurez-vous que vous le voulez vraiment de cette façon.
(SELECT Products.ID, Products.Name
FROM Products
INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)
UNION ALL
(SELECT Products.ID, Products.Name
FROM Products
INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)
UNION ALL
(SELECT Products.ID, Products.Name
FROM Products
INNER JOIN (SELECT RAND()*(SELECT MAX(ID) FROM Products) AS ID) AS t ON Products.ID >= t.ID
WHERE Products.HasImages=1
ORDER BY Products.ID
LIMIT 1)
La première ligne apparaît plus souvent qu'elle ne le devrait
Si vous avez de grands écarts entre les ID dans votre table, les lignes juste après ces écarts auront plus de chances d'être récupérées par cette requête. Dans certains cas, ils apparaîtront beaucoup plus souvent qu'ils ne le devraient. Cela ne peut pas être résolu en général, mais il existe une solution pour un cas particulier courant :lorsqu'il y a un écart entre 0 et le premier ID existant dans une table.
Au lieu de la sous-requête (SELECT RAND()*<max_id> AS ID)
utilisez quelque chose comme (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Supprimer les doublons
La requête, si elle est utilisée telle quelle, peut renvoyer des lignes en double. Il est possible d'éviter cela en utilisant UNION
au lieu de UNION ALL
. De cette façon, les doublons seront fusionnés, mais la requête ne garantit plus de renvoyer exactement 3 lignes. Vous pouvez également contourner ce problème en récupérant plus de lignes que nécessaire et en limitant le résultat externe comme ceci :
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Cependant, il n'y a toujours aucune garantie que 3 lignes seront récupérées. Cela le rend simplement plus probable.