Hãy thử điều này:
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
Điều này đặc biệt hiệu quả trên MyISAM
(kể từ COUNT(*)
là tức thì), nhưng ngay cả trong InnoDB
nó là 10
hiệu quả hơn gấp nhiều lần so với ORDER BY RAND()
.
Ý tưởng chính ở đây là chúng tôi không sắp xếp, nhưng thay vào đó giữ hai biến và tính toán running probability
của một hàng sẽ được chọn ở bước hiện tại.
Xem bài viết này trong blog của tôi để biết thêm chi tiết:
Cập nhật:
Nếu bạn cần chọn trừ một bản ghi ngẫu nhiên, hãy thử cách này:
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
)
)
Điều này giả định ac_id
của bạn được phân phối nhiều hơn hoặc ít hơn đồng đều.