Ošklivé, ale rychlé a náhodné. Velmi rychle se může stát velmi ošklivým, zvláště s laděním popsaným níže, takže se ujistěte, že to opravdu chcete.
(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)
První řádek se zobrazuje častěji, než by měl
Pokud máte velké mezery mezi ID v tabulce, řádky hned za těmito mezerami budou mít větší šanci, že je tento dotaz načte. V některých případech se budou objevovat výrazně častěji, než by měly. To nelze vyřešit obecně, ale existuje oprava pro běžný konkrétní případ:když je mezera mezi 0 a prvním existujícím ID v tabulce.
Místo dílčího dotazu (SELECT RAND()*<max_id> AS ID)
použijte něco jako (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Odstranit duplikáty
Pokud je dotaz použit tak, jak je, může vracet duplicitní řádky. Tomu se lze vyhnout pomocí UNION
místo UNION ALL
. Tímto způsobem budou duplikáty sloučeny, ale dotaz již nezaručuje, že vrátí přesně 3 řádky. I to můžete obejít tím, že načtete více řádků, než potřebujete, a omezíte vnější výsledek takto:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Stále však není zaručeno, že budou načteny 3 řádky. Jen to zvyšuje pravděpodobnost.