Feo, pero rápido y aleatorio. Puede volverse muy feo muy rápido, especialmente con la afinación que se describe a continuación, así que asegúrese de que realmente lo quiere de esta manera.
(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 primera fila aparece con más frecuencia de lo que debería
Si tiene grandes espacios entre los ID en su tabla, las filas justo después de dichos espacios tendrán más posibilidades de ser recuperadas por esta consulta. En algunos casos, aparecerán significativamente más a menudo de lo que deberían. Esto no se puede resolver en general, pero hay una solución para un caso particular común:cuando hay una brecha entre 0 y la primera ID existente en una tabla.
En lugar de subconsulta (SELECT RAND()*<max_id> AS ID)
usa algo como (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Eliminar duplicados
La consulta, si se usa tal cual, puede devolver filas duplicadas. Es posible evitar eso usando UNION
en lugar de UNION ALL
. De esta forma, los duplicados se fusionarán, pero la consulta ya no garantiza devolver exactamente 3 filas. También puede solucionar eso, obteniendo más filas de las que necesita y limitando el resultado externo de esta manera:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Sin embargo, todavía no hay garantía de que se obtengan 3 filas. Simplemente lo hace más probable.