Lelijk, maar snel en willekeurig. Kan erg snel erg lelijk worden, vooral met de hieronder beschreven afstemming, dus zorg ervoor dat je het echt op deze manier wilt.
(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)
Eerste rij verschijnt vaker dan zou moeten
Als u grote hiaten heeft tussen ID's in uw tabel, hebben rijen direct na dergelijke hiaten een grotere kans om door deze zoekopdracht te worden opgehaald. In sommige gevallen zullen ze significant vaker verschijnen dan zou moeten. Dit kan in het algemeen niet worden opgelost, maar er is een oplossing voor een veelvoorkomend bijzonder geval:wanneer er een gat is tussen 0 en de eerste bestaande ID in een tabel.
In plaats van subquery (SELECT RAND()*<max_id> AS ID)
gebruik iets als (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Duplicaten verwijderen
De query, indien gebruikt zoals deze is, kan dubbele rijen retourneren. Het is mogelijk om dat te voorkomen door UNION
. te gebruiken in plaats van UNION ALL
. Op deze manier worden duplicaten samengevoegd, maar de query garandeert niet langer dat exact 3 rijen worden geretourneerd. Je kunt dat ook omzeilen door meer rijen op te halen dan je nodig hebt en het buitenste resultaat als volgt te beperken:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Er is echter nog steeds geen garantie dat 3 rijen worden opgehaald. Het maakt het alleen maar waarschijnlijker.