Grim, men hurtig og tilfældig. Kan blive meget grim meget hurtigt, især med tuning beskrevet nedenfor, så sørg for at du virkelig vil have det på denne måde.
(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)
Første række vises oftere, end den burde
Hvis du har store mellemrum mellem ID'er i din tabel, vil rækker lige efter sådanne huller have større chance for at blive hentet af denne forespørgsel. I nogle tilfælde vil de optræde betydeligt oftere, end de burde. Dette kan ikke løses generelt, men der er en løsning til et almindeligt tilfælde:når der er et hul mellem 0 og det første eksisterende ID i en tabel.
I stedet for underforespørgsel (SELECT RAND()*<max_id> AS ID)
brug noget som (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Fjern dubletter
Forespørgslen, hvis den bruges som den er, kan returnere duplikerede rækker. Det er muligt at undgå det ved at bruge UNION
i stedet for UNION ALL
. På denne måde vil dubletter blive slået sammen, men forespørgslen garanterer ikke længere at returnere nøjagtigt 3 rækker. Du kan også omgå det ved at hente flere rækker, end du har brug for, og begrænse det ydre resultat på denne måde:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Der er dog stadig ingen garanti for, at 3 rækker bliver hentet. Det gør det bare mere sandsynligt.