18

这是在我的网站上订购搜索结果的问题,

进行搜索时,内容页面上会出现随机结果,该页面也包括分页。我将用户作为我的 SQL 查询。

SELECT * FROM table ORDER BY RAND() LIMIT 0,10;

所以我的问题是

  1. 我需要确保每次用户访问下一页时,他们已经看到的结果不会再次出现(在下一个查询中排除它们,以一种内存有效的方式,但仍按 rand() 排序)

  2. 每次访问者进入第一页时,都会有一组不同的结果,是否可以使用分页,或者排序总是随机的。

  3. 我可以在 MYSQL 中使用种子,但是我不确定如何实际使用它..

4

6 回答 6

55

使用 RAND(SEED)。引用文档:“如果指定了常量整数参数 N,则将其用作种子值。 ”(http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_rand)。

在上面的示例中,结果顺序是 rand,但始终相同。您只需更改种子即可获得新订单。

SELECT * FROM your_table ORDER BY RAND(351);

您可以在用户每次点击第一个结果页面时更改种子并将其存储在用户会话中。

于 2014-05-17T02:01:34.037 回答
16

MySQL 中的随机排序是一个棘手的问题。过去,我通常选择尽可能绕过这个问题。通常,用户不会超过一次或两次返回到这样的一组页面。因此,这使您有机会避免所有各种令人作呕的随机顺序实现,而支持几个简单但不是 100% 的随机解决方案。

解决方案 1

从已编入索引以供排序的许多现有列中进行选择。这可以包括创建时间、修改时间或您可以排序的任何其他列。当用户第一次访问该站点时,将这些方便地放在一个数组中,随机选择一个,然后随机选择ASCDESC

在您的情况下,每次用户返回第 1 页时,选择新的内容并将其存储在会话中。每个后续页面,您都可以使用该排序来生成一组一致的分页。

解决方案 2

您可以有一个额外的列来存储用于排序的随机数。显然,它应该被索引。定期运行以下查询;

更新表 SET rand_col = RAND();

这可能不适用于您的规格,因为您似乎要求每个用户每次点击第 1 页时都看到不同的东西。

于 2012-05-24T02:55:10.170 回答
1

首先,您应该停止使用 ORDER BY RAND 语法。这将不利于大量行的性能。

您需要手动确定 LIMIT 约束。如果您仍想使用随机结果并且您不希望用户在下一页看到相同的结果,唯一的方法是将此搜索会话的所有结果保存在数据库中,并在用户导航到下一页时操作此信息。

在网页设计中你应该明白的下一件事——在你的网站上使用任何随机数据块对用户的视觉感知非常、非常、非常不利。

于 2012-05-24T00:30:31.493 回答
0

的组合

  1. 随机排序
  2. 分页
  3. HTTP(无状态)

就像它一样丑陋:1. 和 2. 一起需要某种“持久随机性”,而 3. 使这更难实现。最重要的是 1. 不是 RDBMS 优化的工作。

我的建议取决于您的数据集有多大:

几行(约<1K):

  • 在第一个查询中选择所有 PK 值(第一页)
  • 在 PHP 中随机播放这些
  • 在会话中存储洗牌列表
  • 对于每个页面调用,根据存储的 PK 选择数据

许多行(10K+):

这假设,您有一个AUTO_INCREMENT唯一的密钥,称为ID具有可管理数量的孔。如果需要,使用 amintenace 脚本(高删除率)

  • 使用使用会话 ID 等参数化的改组函数来创建函数rand_id(continuous_id)
  • 如果您需要例如记录 100,000 到 100,009 计算$a=array(rand_id(100,000), rand_id(100,001), ... rand_id(100,009));
  • $a=implode(',',$a);
  • $sql="SELECT foo FROM bar WHERE ID IN($a) ORDER BY FIELD(ID,$a)";
  • 要解决您 ID 中的漏洞,请选择过多的记录(并丢弃 exess),循环选择的记录太少。
于 2012-05-24T01:01:53.870 回答
0

你有几个问题要处理!我建议你一步一步来。

第一个问题: 他们已经看到的结果不再出现

  1. 返回的每个项目,将其存储在一个数组中。(假设id示例中的索引)
  2. 当用户转到下一页时,将NOT IN传递给查询:

MySQL 查询

SELECT * FROM table WHERE id NOT IN (1, 14, 25, 645) ORDER BY RAND() LIMIT 0,10;

这样做是为了匹配所有id不是 1、14、25 或 645 的值。


就性能问题而言: 以内存有效的方式

SELECT RAND( )
FROM table
WHERE id NOT
IN ( 1, 14, 25, 645 )
LIMIT 0 , 10

显示第 0 - 9 行(共 10 行,查询耗时 0.0004 秒)

SELECT *
FROM table
WHERE id NOT
IN ( 1, 14, 25, 645 )
ORDER BY RAND( )
LIMIT 0 , 10

显示第 0 - 9 行(共 10 行,查询耗时 0.0609 秒)

所以,不要使用 ORDER BY RAND(),最好使用 SELECT RAND()。

于 2012-05-24T00:37:11.113 回答
0

我会让你的 PHP 生成你的随机记录数或行来检索,将它们传递给你的查询,并在用户的客户端上保存一个 cookie,表明他们已经看到了哪些记录。

该用户特定数据没有理由存在于服务器上(除非您正在跟踪它,但无论如何它都是随机的,所以谁在乎)。

于 2012-05-24T00:30:43.543 回答