MYSQL 从每个类别中随机选择 2 行

Imr*_*l.H 1 mysql sql select

我有一个包含如下列的 mysql 表:

`qid`, `category`, `question`, `choice_1`, `choice_2`, `choice_3`, `answer`
Run Code Online (Sandbox Code Playgroud)

在这个表中,我有 2000 个数据,有 7 个不同的“类别”。我想从这个表中获取 15 个随机行,每个类别的数量相等。由于我有 7 个类别,因此不可能从每个类别中获得相同数量的行。在这种情况下,我可以从一个类别中获得 3 个。如何通过一个查询实现这一目标?

我想从每个类别中获取 2 行。然后我总共会有14行,然后我可以从表中随机获取1行并合并记录。请给我看一个示例查询。谢谢。这是我的实际表结构:

CREATE TABLE IF NOT EXISTS `difi_questions` (
  `qid` smallint(6) NOT NULL AUTO_INCREMENT,
  `category` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `question` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `choice_1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `choice_2` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `choice_3` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `answer` enum('1','2','3') COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`qid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1959 ;
Run Code Online (Sandbox Code Playgroud)

dog*_*ose 5

只需按照您的描述为每个类别提取 2 个,最后随机提取一个。它不是一个查询,而是一个结果集,这可能是您需要的:

SELECT * FROM (SELECT * FROM questions WHERE category= 1 ORDER BY rand() limit 0,2) as t1
UNION
SELECT * FROM (SELECT * FROM questions WHERE category= 2 ORDER BY rand() limit 0,2) as t2
UNION 
SELECT * FROM (SELECT * FROM questions WHERE category= 3 ORDER BY rand() limit 0,2) as t3
UNION
...
Run Code Online (Sandbox Code Playgroud)

(嵌套的 Select 允许您按类别按 rand() 排序)到目前为止没有什么特别的 - 每个类别 2 个随机问题。

现在棘手的部分是添加第 15 个元素,而不选择您已有的任何元素。

要通过“一个”调用实现这一点,您可以执行以下操作:

  • 选择您在上面选择的 14 个问题的子集。
  • 将其与数据库中一组未分类的随机排序事物联合起来。(限制 0,15)
  • 从此结果中全选,限制为 0,15。

  • 如果已选择 LAST 子查询的前 14 个元素 - 它们将被删除,因为UNION,并保证独立的第 15 个元素。

  • 如果最终的内部查询也选择了 15 个不同的问题,则外部限制 0,15 只会将其中的第一个纳入结果。

就像是:

SELECT * FROM (
    SELECT * FROM (SELECT * FROM questions WHERE category= 1 ORDER BY rand() limit 0,2) as t1
    UNION
    SELECT * FROM (SELECT * FROM questions WHERE category= 2 ORDER BY rand() limit 0,2) as t2
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 3 ORDER BY rand() limit 0,2) as t3
    UNION
    ...
    UNION
    SELECT * FROM (SELECT * FROM questions ORDER BY rand() LIMIT 0,15) as t8
) AS tx LIMIT 0,15
Run Code Online (Sandbox Code Playgroud)

这有点难看,但应该完全满足您的需求:来自每个类别的 2 个随机问题,最后是尚未从任何类别中选择的随机问题。一共15道题随时问。

(Sidenode:您也可以运行第二个查询,NOT IN ()用于在确定 7 个类别的 14 个问题后禁止已选择的问题。)

编辑:不幸的是 SQL Fiddle 目前不起作用。这是一些小提琴代码:

CREATE TABLE questions (id int(10), category int(10), question varchar(20));

INSERT INTO questions (id, category, question)VALUES(1,1,"Q1");
INSERT INTO questions (id, category, question)VALUES(2,1,"Q2");
INSERT INTO questions (id, category, question)VALUES(3,1,"Q3");
INSERT INTO questions (id, category, question)VALUES(4,2,"Q4");
INSERT INTO questions (id, category, question)VALUES(5,2,"Q5");
INSERT INTO questions (id, category, question)VALUES(6,2,"Q6");
INSERT INTO questions (id, category, question)VALUES(7,3,"Q7");
INSERT INTO questions (id, category, question)VALUES(8,3,"Q8");
INSERT INTO questions (id, category, question)VALUES(9,3,"Q9");
INSERT INTO questions (id, category, question)VALUES(10,4,"Q10");
INSERT INTO questions (id, category, question)VALUES(11,4,"Q11");
INSERT INTO questions (id, category, question)VALUES(12,4,"Q12");
INSERT INTO questions (id, category, question)VALUES(13,5,"Q13");
INSERT INTO questions (id, category, question)VALUES(14,5,"Q14");
INSERT INTO questions (id, category, question)VALUES(15,5,"Q15");
INSERT INTO questions (id, category, question)VALUES(16,6,"Q16");
INSERT INTO questions (id, category, question)VALUES(17,6,"Q17");
INSERT INTO questions (id, category, question)VALUES(18,6,"Q18");
INSERT INTO questions (id, category, question)VALUES(19,7,"Q19");
INSERT INTO questions (id, category, question)VALUES(20,7,"Q20");
INSERT INTO questions (id, category, question)VALUES(21,7,"Q21");
Run Code Online (Sandbox Code Playgroud)

询问

SELECT * FROM (
    SELECT * FROM (SELECT * FROM questions WHERE category= 1 ORDER BY rand() limit 0,2) as t1
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 2 ORDER BY rand() limit 0,2) as t2
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 3 ORDER BY rand() limit 0,2) as t3
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 4 ORDER BY rand() limit 0,2) as t4
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 5 ORDER BY rand() limit 0,2) as t5
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 6 ORDER BY rand() limit 0,2) as t6
    UNION 
    SELECT * FROM (SELECT * FROM questions WHERE category= 7 ORDER BY rand() limit 0,2) as t7
    UNION 
    SELECT * FROM (SELECT * FROM questions ORDER BY rand() LIMIT 0,15) as t8
) AS tx LIMIT 0,15
Run Code Online (Sandbox Code Playgroud)

示例数据包含每种类型的 3 个问题,导致第 15 个问题(最后一行)始终是某个类别中剩余的一个。