PHP随机排序的MySQL分页

时间:2012-05-24 00:21:32

标签: php mysql

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

进行搜索时,内容页面上会显示随机结果,此页面也包含分页。我用户跟随我的SQL查询。

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

所以我的问题是

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

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

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

6 个答案:

答案 0 :(得分:37)

使用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);

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

答案 1 :(得分:13)

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

解决方案1 ​​

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

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

解决方案2

您可以使用其他列存储随机数进行排序。显然应该将其编入索引。定期运行以下查询;

  

UPDATE表SET rand_col = RAND();

这可能对您的规格不起作用,因为您似乎要求每个用户在每次点击第1页时都会看到不同的内容。

答案 2 :(得分:0)

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

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

您应该了解网页设计的下一件事 - 使用您网站上的任何随机数据块对于用户的视觉感知非常非常非常糟糕。

答案 3 :(得分:0)

我希望你的PHP生成你的随机记录数字或行来检索,将它们传递给你的查询,并在用户的客户端保存一个cookie,说明他们已经看过的记录。

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

答案 4 :(得分:0)

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

第一期: 结果他们已经看到不再出现

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

    MySQL查询

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

    这样做的目的是匹配非1,1,25或645的所有id


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

    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()。

答案 5 :(得分:0)

的组合
  1. 随机排序
  2. 分页
  3. HTTP(无状态)
  4. 和它一样丑陋:1。和2.一起需要某种“持久的随机性”,而3.使得这更难实现。除此之外,这不是RDBMS优化的工作。

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

    几行(约<1K):

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

    许多行(10K +):

    这假设您有一个名为AUTO_INCREMENT的{​​{1}}唯一密钥,其中有一些可管理的漏洞。如果需要,使用amintenace脚本(高删除率)

    • 使用通过例如参数化的混洗函数用于创建函数ID
    • 的会话ID
    • 如果您需要,例如记录100,000到100,009计算rand_id(continuous_id)
    • $a=array(rand_id(100,000), rand_id(100,001), ... rand_id(100,009));
    • $a=implode(',',$a);
    • 要处理你的身份证上的漏洞,请选择一些记录太多(并扔掉这些记录),循环选择的记录太少。