use*_*120 5 php mysql database-schema
我正在尝试准确显示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;
Run Code Online (Sandbox Code Playgroud)
表结构:
table Articles
- id (int)
- category (varchar)
- title (varchar)
- image (varchar)
- link (varchar)
- Counter (int)
- dateStamp (datetime)
Run Code Online (Sandbox Code Playgroud)
和
select floor(rand() * m.maxId + 1) as randomId
from Articles a
join (SELECT MAX(id) maxId FROM Articles) m
limit 100
Run Code Online (Sandbox Code Playgroud)
您将创建 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
Run Code Online (Sandbox Code Playgroud)
子选择中的最佳值LIMIT取决于 id 中的间隙百分比。100应该足够而且快。
更新
如果需要过滤,category可以在andWHERE a.category = 'entertainment'之前添加子句。但在这种情况下,您将需要调整生成的随机 ID 的数量。ORDER BYLIMIT
例如:如果您插入了 1M 篇文章,但其中 10% 被删除,那么平均有 90 个随机生成的 id 确实存在。如果现在 10% 的文章具有category = 'entertainment',则平均有 9 个随机行将匹配该条件。平均数- 可能是 3,也可能是 16。因此,您需要生成更多随机 ID 以确保您至少获得 6 篇文章。通过LIMIT 1000子选择,您将平均获得 90 篇随机娱乐文章。这样你就不太可能得到少于 6 的结果。所以你需要知道你的表的统计数据才能选择一个好的LIMIT.
该子句的另一个问题WHERE是 MySQL 可能会反转连接顺序以使用索引进行过滤。对于少量生成的随机 id 来说,这可能会更快,但如果子LIMIT选择中的 id 很大,则可能会更慢。STRIGHT_JOIN您可以通过使用而不是JOIN-来强制连接顺序,但在我的测试中LIMIT 10000它并没有产生可测量的差异。
如果您的条件过于选择性(例如,只有 1% 的文章有category='entertainment'),则简单的ORDER BY RAND()可能会更快,因为否则您将需要创建太多随机 id。但最多 10K 行匹配您的条件ORDER BY RAND()就足够快了。