我正在尝试准确显示6个随机娱乐内容'条目,但在我当前的查询中,它获得1到6之间的随机数,并显示该条目数。如何更新此查询以使其显示我的文章表中的6个随机娱乐条目?另外,我不想做ORDER BY RAND()因为我的桌子会加班加点。这是我当前的疑问:
SELECT
r1.*
FROM
Articles AS r1
INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM Articles)) AS id) AS r2
WHERE
r1.id >= r2.id
AND r1.category = 'entertainment'
LIMIT 6;
表格结构:
table Articles
- id (int)
- category (varchar)
- title (varchar)
- image (varchar)
- link (varchar)
- Counter (int)
- dateStamp (datetime)
答案 0 :(得分:0)
用
select floor(rand() * m.maxId + 1) as randomId
from Articles a
join (SELECT MAX(id) maxId FROM Articles) m
limit 100
您将创建100个随机ID。我拿100是因为你的id列中有空白,所以没有得到足够的现有id的概率会非常小。然后,您可以使用该结果仅选择具有这些ID的6行:
select distinct a.*
from (
select id, floor(rand() * m.maxId + 1) as randomId
from Articles a
join (SELECT MAX(id) maxId FROM Articles) m
limit 100
) r
join Articles a on a.id = r.randomId
order by r.id -- only need it for small tables. will slow down the query on big tables
limit 6
子选择中LIMIT
的最佳值取决于您的ID中的间隙百分比。 100应该足够快。
<强>更新强>
如果您需要按category
进行过滤,则可以在WHERE a.category = 'entertainment'
和ORDER BY
之前添加LIMIT
子句。但在这种情况下,您需要调整生成的随机ID的数量。
例如:如果您已插入1M文章但其中10%被删除,则确实存在90个随机生成的平均ID。如果现在有10%的文章有category = 'entertainment'
,则平均有9个随机行符合条件。 平均值表示 - 它可能是3,也可能是16.因此,您需要生成更多随机ID以确保您获得至少6篇文章。在子选择中LIMIT 1000
,您将获得平均90个随机娱乐文章。这样你就不太可能得到少于6.所以你需要知道你的表的统计数据才能选择一个好的LIMIT
。
WHERE
子句的另一个问题是MySQL可能会反转连接顺序以使用索引进行过滤。对于少量生成的随机ID,这可能会更快,但如果子选择中的LIMIT
很大,则可能会更慢。您可以使用STRIGHT_JOIN
而不是JOIN
强制加入订单 - 但在我使用LIMIT 10000
的测试中,它没有制作
可衡量的差异。
如果您的情况过于挑剔(例如只有1%的文章有category='entertainment'
),那么简单的ORDER BY RAND()
会更快,因为否则您需要创建太多的随机ID。但是,符合条件ORDER BY RAND()
的最多10K行将足够快。
答案 1 :(得分:0)
您的“娱乐”条目应该都有唯一的ID,应该是整数。
如果是这种情况,您可以使用PHP的rand()函数在1和您拥有的条目数之间生成6个随机int。这是我写的一个可能有用的函数。
function selectSixRandomEntries() {
$queryWhere = "";
$i = 0;
while($i < 6) {
$randomNumber = rand(1, 200);
if (strpos($queryWhere, $randomNumber) == -1)
continue;
$queryWhere .= "r1.id = " . rand(1, 200);
if ($i != 5)
$queryWhere .= " OR ";
$i++;
}
return $queryWhere
}
要使用它,你可以尝试
$query = "SELECT
r1.*
FROM
Articles AS r1
INNER JOIN (SELECT(RAND() * (SELECT MAX(id) FROM Articles)) AS id) AS r2
WHERE
" . selectSixRandomEntries() . "
AND r1.category = 'entertainment'
LIMIT 6";