Ful, men snabb och slumpmässig. Kan bli väldigt fult väldigt snabbt, speciellt med justering som beskrivs nedan, så se till att du verkligen vill ha det så här.
(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örsta raden visas oftare än den borde
Om du har stora luckor mellan ID:n i din tabell, kommer rader direkt efter sådana luckor att ha större chans att hämtas av den här frågan. I vissa fall kommer de att dyka upp betydligt oftare än de borde. Detta kan inte lösas generellt, men det finns en fix för ett vanligt särskilt fall:när det finns ett gap mellan 0 och det första befintliga ID:t i en tabell.
Istället för underfrågan (SELECT RAND()*<max_id> AS ID)
använd något som (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Ta bort dubbletter
Frågan, om den används som den är, kan returnera dubbletter av rader. Det är möjligt att undvika det genom att använda UNION
istället för UNION ALL
. På detta sätt kommer dubbletter att slås samman, men frågan garanterar inte längre att den returnerar exakt 3 rader. Du kan också komma runt det genom att hämta fler rader än du behöver och begränsa det yttre resultatet så här:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Det finns fortfarande ingen garanti för att 3 rader kommer att hämtas. Det gör det bara mer sannolikt.