Coba ini:
SELECT *
FROM (
SELECT @cnt := COUNT(*) + 1,
@lim := 10
FROM t_random
) vars
STRAIGHT_JOIN
(
SELECT r.*,
@lim := @lim - 1
FROM t_random r
WHERE (@cnt := @cnt - 1)
AND RAND(20090301) < @lim / @cnt
) i
Ini sangat efisien di MyISAM
(karena COUNT(*)
instan), tetapi bahkan dalam InnoDB
itu 10
kali lebih efisien daripada ORDER BY RAND()
.
Ide utamanya di sini adalah bahwa kita tidak mengurutkan, tetapi menyimpan dua variabel dan menghitung running probability
dari baris yang akan dipilih pada langkah saat ini.
Lihat artikel ini di blog saya untuk detail lebih lanjut:
Pembaruan:
Jika Anda perlu memilih satu rekaman acak, coba ini:
SELECT aco.*
FROM (
SELECT minid + FLOOR((maxid - minid) * RAND()) AS randid
FROM (
SELECT MAX(ac_id) AS maxid, MIN(ac_id) AS minid
FROM accomodation
) q
) q2
JOIN accomodation aco
ON aco.ac_id =
COALESCE
(
(
SELECT accomodation.ac_id
FROM accomodation
WHERE ac_id > randid
AND ac_status != 'draft'
AND ac_images != 'b:0;'
AND NOT EXISTS
(
SELECT NULL
FROM accomodation_category
WHERE acat_id = ac_category
AND acat_slug = 'vendeglatohely'
)
ORDER BY
ac_id
LIMIT 1
),
(
SELECT accomodation.ac_id
FROM accomodation
WHERE ac_status != 'draft'
AND ac_images != 'b:0;'
AND NOT EXISTS
(
SELECT NULL
FROM accomodation_category
WHERE acat_id = ac_category
AND acat_slug = 'vendeglatohely'
)
ORDER BY
ac_id
LIMIT 1
)
)
Ini mengasumsikan ac_id
. Anda 's didistribusikan kurang lebih merata.