Грозно, но бързо и произволно. Може да стане много грозно много бързо, особено с настройката, описана по-долу, така че се уверете, че наистина го искате по този начин.
(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)
Първият ред се появява по-често, отколкото трябва
Ако имате големи пропуски между идентификаторите във вашата таблица, редовете непосредствено след такива пропуски ще имат по-голям шанс да бъдат извлечени от тази заявка. В някои случаи те ще се появяват значително по-често, отколкото трябва. Това не може да бъде решено като цяло, но има корекция за често срещан конкретен случай:когато има празнина между 0 и първия съществуващ идентификатор в таблица.
Вместо подзаявка (SELECT RAND()*<max_id> AS ID)
използвайте нещо като (SELECT <min_id> + RAND()*(<max_id> - <min_id>) AS ID)
Премахване на дубликати
Заявката, ако се използва както е, може да върне дублиращи се редове. Възможно е да се избегне това, като се използва UNION
вместо UNION ALL
. По този начин дубликатите ще бъдат обединени, но заявката вече не гарантира, че ще върне точно 3 реда. Можете да заобиколите и това, като извлечете повече редове, отколкото са ви необходими и ограничите външния резултат по следния начин:
(SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
UNION (SELECT ... LIMIT 1)
...
UNION (SELECT ... LIMIT 1)
LIMIT 3
Все още няма гаранция, че ще бъдат извлечени 3 реда. Това просто го прави по-вероятно.