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

我的目标

我试图检索多个随机行,其中只包含唯一的用户ID,但类型列是随机的 – 类型只能是0或1.有问题的表在任何给定时间都包含少于1,000行.

我的桌子

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

要排除什么

使用ORDER BY RAND()是不可行的,因为在任何给定时刻应用程序都会执行至少18,000种这类查询并导致高负载.使用SELECT DISTINCT或GROUP BY(显然)更有效,并且总是选择唯一的用户ID,但是类型总是等于0且具有可接受的负载.

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

谢谢.

最佳答案 我对你的问题的理解是,对于每个用户ID,你有两个条目,但是想要随机提取一个.

要实现这一点,您应该为每个唯一的用户ID生成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);

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

点赞