如何从MySQL中的每个类别获取RANDOM记录?

may*_*ʎɐɯ 6 mysql sql

在我的MySQL数据库中,我有一个表,在不同的类别中有不同的问题.

我想编写一个返回EACH类别的3个RANDOM问题的SQL语句.

以下是数据库记录的示例:

id  question    category
1   Question A  1
2   Question B  1
3   Question C  1
4   Question D  1
5   Question D  1
6   Question F  2
7   Question G  2
8   Question H  2
9   Question I  2
10  Question J  2
11  Question K  3
12  Question L  3
13  Question M  3
14  Question N  3
15  Question O  3
16  Question P  3
Run Code Online (Sandbox Code Playgroud)

以下是从上面列表中的每个类别的所有问题中选择并随机排列的3个随机的输出/结果:

2   Question B  1
4   Question D  1
3   Question C  1
10  Question J  2
7   Question G  2
9   Question I  2
11  Question K  3
15  Question P  3
13  Question M  3
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经使用以下语句进行测试:

SELECT * FROM `random` ORDER BY RAND() LIMIT 0,3;
Run Code Online (Sandbox Code Playgroud)

这只返回所有类别的3个RANDOM问题.

之后我在这个链接上查找了例子: MYSQL选择每个类别的随机

并尝试了这个:

(SELECT * FROM `random` WHERE category = 1 ORDER BY RAND() LIMIT 3)
UNION ALL
(SELECT * FROM `random` WHERE category = 2 ORDER BY RAND() LIMIT 3)
UNION ALL
(SELECT * FROM `random` WHERE category = 3 ORDER BY RAND() LIMIT 3)
Run Code Online (Sandbox Code Playgroud)

但在这里我需要手动添加每个类别.

我的问题:我很奇怪是否可以从所有类别的每个类别(自动)中获取3个RANDOM记录/行?


编辑

这不是问题的一部分,而是帮助.

虚拟数据创建者 查询代码将调用表random并创建一个调用的存储过程create_random,当您运行存储过程时,它将在随机表中创建随机虚拟数据:

DELIMITER $$
DROP TABLE IF EXISTS `random`;
DROP PROCEDURE IF EXISTS `create_random` $$

CREATE TABLE `random` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `question` VARCHAR(50) NULL DEFAULT NULL,
    `category` VARCHAR(50) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=401
;

CREATE DEFINER=`root`@`localhost`
PROCEDURE `create_random`()
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''

BEGIN

DECLARE v_max int unsigned DEFAULT 100;
DECLARE v_counter int unsigned DEFAULT 0;
DECLARE cat_counter int unsigned DEFAULT 0;

  TRUNCATE TABLE `random`;
  START TRANSACTION;
  WHILE v_counter < v_max DO
    IF v_counter %10=0 THEN SET cat_counter=cat_counter+1;
    END IF;
    INSERT INTO `random` (question, category) VALUES ( CONCAT('Question', FLOOR(0 + (RAND() * 65535))), cat_counter );
    SET v_counter=v_counter+1;
  END WHILE;
  COMMIT;
END
Run Code Online (Sandbox Code Playgroud)

注意:我尝试了所有答案,一切正常.Gordon Linoff和pjanaway回答选择RANDOM只有前3或下3问题,我已经检查了Gordon的答案,因为他先回答,但这并不意味着其他答案都不好,所有这些都很好,这取决于用户选择正确答案或答案组合.我喜欢所有答案并将其投票.德鲁皮尔斯对这个问题的回答很新,现在更有趣,几乎接近目标.谢谢大家.

Gor*_*off 5

是的,您可以通过枚举行然后获取前三行来实现:

select r.id, r.question, r.category
from (select r.*,
             (@rn := if(@c = category, @rn + 1,
                        if(@c := category, 1, 1)
                       )
             ) as seqnum
      from `random` r cross join
           (select @rn := 0, @c := -1) params
      order by category, rand()
     ) r
where seqnum <= 3;
Run Code Online (Sandbox Code Playgroud)


pja*_*jau 5

除了其他答案,这也是另一种解决方法。

SELECT r.* FROM random r
WHERE (
  SELECT COUNT(*) FROM random r1
  WHERE r.category = r1.category AND r.id < r1.id
) <= 2
ORDER BY r.category ASC, RAND()
Run Code Online (Sandbox Code Playgroud)