由于您使用的是 MySQL,您可以尝试使用以下 SQL 查询,首先从表中获取计数,然后根据该计数选择随机偏移量。然后它准备一个语句,以便可以使用计算的偏移量并执行该语句。
SELECT @count := COUNT(*) FROM table AS a JOIN table AS b ON ( a.id <> b.id ) WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100;
SET @offset = CONVERT(FLOOR(RAND() * @count), SIGNED);
PREPARE mystatement FROM "SELECT
a.id as aid, a.data1 as adata1, a.data2 as adata2
b.id as bid, b.data1 as bdata1, b.data2 as bdata2
FROM table AS a
JOIN table AS b ON ( a.id <> b.id )
WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100 LIMIT ?, 1";
EXECUTE mystatement USING @offset;
DEALLOCATE PREPARE mystatement;
在大型数据集上的执行速度应该比 快ORDER BY RAND()
,请尝试让我知道... ;-)
编辑
查询将无法在 phpmyadmin 上使用,因此请使用 MySQL 控制台运行它们或编写一个 php 脚本,其中有两个选项,第一个是让 mysql 完成工作:
mysql_query('SELECT @count := COUNT(*) FROM table AS a JOIN table AS b ON ( a.id <> b.id ) WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100');
mysql_query('SET @offset = CONVERT(FLOOR(RAND() * @count), SIGNED)');
mysql_query('PREPARE mystatement FROM "SELECT
a.id as aid, a.data1 as adata1, a.data2 as adata2
b.id as bid, b.data1 as bdata1, b.data2 as bdata2
FROM table AS a
JOIN table AS b ON ( a.id <> b.id )
WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100 LIMIT ?, 1"');
$res = mysql_query('EXECUTE mystatement USING @offset');
$row = mysql_fetch_assoc($res);
print_r($row);
第二个可能更快的选择包括使用 MySQL 完成一部分工作,而另一部分使用编程语言(在我们的例子中是 PHP):
$res = mysql_query("SELECT COUNT(*) FROM table AS a JOIN table AS b ON ( a.id <> b.id ) WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100')");
$row = mysql_fetch_array($res);
$offset = rand(0, $row[0]-1);
$res = mysql_query("SELECT
a.id as aid, a.data1 as adata1, a.data2 as adata2
b.id as bid, b.data1 as bdata1, b.data2 as bdata2
FROM table AS a
JOIN table AS b ON ( a.id <> b.id )
WHERE (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100 LIMIT $offset, 1");
$row = mysql_fetch_assoc($res);
我发现的另一种加快 ORDER BY RAND() 的替代方法包括如下查询:
SELECT
a.id as aid, a.data1 as adata1, a.data2 as adata2
b.id as bid, b.data1 as bdata1, b.data2 as bdata2
FROM table AS a
JOIN table AS b ON ( a.id <> b.id )
WHERE (RAND() < (SELECT ((1/COUNT(*))*10) FROM table AS a JOIN table AS b ON ( a.id <> b.id ) ) )
AND (a.data1=1 AND b.data1=1) AND ABS( a.rating - b.rating ) <100
ORDER BY RAND()
LIMIT 1
不要忘记告诉我你得到的结果;-)。