如何在没有id / auto_increment列的MySQL中检索多个随机行?

时间:2012-09-30 23:28:31

标签: mysql

我的目标

我正在尝试检索仅包含唯一userid的多个随机行,但type列是随机的 - type只能是0或{{1 }}。有问题的表在任何给定时间都包含少于1,000行。

我的表

1

示例数据

CREATE TABLE tbl_message_queue (
  userid bigint(20) NOT NULL,
  messageid varchar(20) NOT NULL,
  `type` int(1) NOT NULL,
  PRIMARY KEY (userid,messageid,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

排除什么

使用userid | messageid | type --------------------------------------------------- 4353453 | 518423942 | 0 4353453 | 518423942 | 1 2342934 | 748475435 | 0 2342934 | 748475435 | 1 7657529 | 821516543 | 0 7657529 | 821516543 | 1 0823546 | 932843285 | 0 0823546 | 932843285 | 1 是不可行的,因为在任何给定时刻应用程序都会执行至少18,000种这类查询并导致高负载。使用ORDER BY RAND()SELECT DISTINCT(显然)效率更高,并且始终会选择唯一的GROUP BY,但userid将始终等于type且负载可接受。

常用方法是创建0列,但我正在寻找另一种方式 。组主键不能根据需要进行更改并深入集成到我们的应用程序中,但每列的结构都可以更改。

感谢。

1 个答案:

答案 0 :(得分:2)

我对您的问题的理解是,对于每个userid,您有两个条目,但想要随机提取一个

要实现这一点,您应该为每个唯一userid生成0到1之间的随机值,然后使用起始列表加入此列表:

SELECT a.* FROM tbl_message_queue AS a
    JOIN ( SELECT userid, FLOOR(2*RAND()) AS type 
           FROM tbl_message_queue GROUP BY userid ) AS b
    ON ( a.userid = b.userid AND a.type = b.type );

但如果ORDER BY RAND()不适合你,也许我们应该妥协。

在上面的序列中,任何两个用户ID将不相关 - 即,用户A获得类型0的事实不会告诉您用户B将会出现什么。

根据用例,可以通过两个查询获得较少随机(但“明显随机”)的序列:

SELECT @X := FLOOR(2*RAND()), @Y := POW(2,FLOOR(2+14*RAND()))-1;

SELECT * FROM tbl_message_queue WHERE (((userid % @Y) & 1) XOR type XOR @X);

这样,您可以获得似乎随机抽取的内容。真正发生的是用户ID是相关的,你只有几十种不同的提取可能。但是只使用简单的运算符,而且没有JOIN,这个查询非常快。