mysqlsqlanalytical

mysql take N random from group


I'm trying to build a query that it would be easy with OVER(), but mysql doesn't have these analytical features...

I must take 2 random questions from groups with IdTopic 1 or 2 and 1 random questions from topics 3 and 4.

 CREATE TABLE Questions (
  IdQuestion INT
  ,IdTopic TINYINT
  ,Question VARCHAR(50)
  ,Answer TINYINT
)

INSERT INTO Questions VALUES(1,1,'T1 Q1 A0',0);
INSERT INTO Questions VALUES(2,1,'T1 Q2 A1',1);
INSERT INTO Questions VALUES(3,1,'T1 Q3 A1',1);
INSERT INTO Questions VALUES(4,1,'T1 Q4 A0',0);
INSERT INTO Questions VALUES(5,1,'T1 Q5 A0',0);
INSERT INTO Questions VALUES(6,1,'T1 Q6 A1',1);
INSERT INTO Questions VALUES(7,1,'T1 Q7 A1',1);
INSERT INTO Questions VALUES(8,1,'T1 Q8 A0',0);

INSERT INTO Questions VALUES(9,2,'T2 Q9 A0',0);
INSERT INTO Questions VALUES(10,2,'T2 Q10 A0',0);
INSERT INTO Questions VALUES(11,2,'T2 Q11 A1',1);
INSERT INTO Questions VALUES(12,2,'T2 Q12 A1',1);
INSERT INTO Questions VALUES(13,2,'T2 Q13 A1',1);

INSERT INTO Questions VALUES(14,3,'T3 Q14 A0',0);
INSERT INTO Questions VALUES(15,3,'T3 Q15 A1',1);
INSERT INTO Questions VALUES(16,3,'T3 Q16 A1',1);
INSERT INTO Questions VALUES(17,3,'T3 Q17 A0',0);
INSERT INTO Questions VALUES(18,3,'T3 Q18 A1',1);

INSERT INTO Questions VALUES(19,4,'T3 Q19 A0',0);
INSERT INTO Questions VALUES(20,4,'T3 Q20 A0',0);
INSERT INTO Questions VALUES(21,4,'T3 Q21 A0',0);
INSERT INTO Questions VALUES(22,4,'T3 Q22 A0',0);
INSERT INTO Questions VALUES(23,4,'T3 Q23 A1',1);

The result must be:

6 total rows

With OVER function I would partition data by IdTopic ordering by RANDOM and then filter by rownumber <= 1 or <=2..

Thanks to everyone :)


Solution

  • Probably the simplest way to do this in MySQL (or most databases) is just to use union all. Unless you have a lot of questions (many thousands), the performance should be fine:

    (select q.*
     from questions q
     where idTopic = 1
     order by rand()
     limit 2
    ) union all
    (select q.*
     from questions q
     where idTopic = 2
     order by rand()
     limit 2
    ) union all
    (select q.*
     from questions q
     where idTopic = 3
     order by rand()
     limit 1
    ) union all
    (select q.*
     from questions q
     where idTopic = 4
     order by rand()
     limit 1
    );