在我的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的答案,因为他先回答,但这并不意味着其他答案都不好,所有这些都很好,这取决于用户选择正确答案或答案组合.我喜欢所有答案并将其投票.德鲁皮尔斯对这个问题的回答很新,现在更有趣,几乎接近目标.谢谢大家.
是的,您可以通过枚举行然后获取前三行来实现:
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)
除了其他答案,这也是另一种解决方法。
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)