Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL join, ORDER BY RAND() then sort ASC (preferably using Sequelize)

I'd like some help with this MySQL query. Ideally, I'd generate it using the node.js Sequelize ORM.

The tables are:

Questions: id, question
Answers: id, question_id, answer

My Sequelize code is:

models.questions.findAll({
  where: {
    id: {
      $notIn: not_in
    }
  },
    order: [['id','ASC'], [models.answers, 'id', 'ASC']],
    attributes: ['id', 'question'],
    include: [{
        model: models.answers,
        attributes: ['id', 'question_id', 'answer'],
    }]
})

With not_in set to -1, Sequelize generates this query:

SELECT `questions`.`id`, 
       `questions`.`question`, 
       `answers`.`id`          AS `answers.id`, 
       `answers`.`question_id` AS `answers.question_id`, 
       `answers`.`answer`      AS `answers.answer` 
FROM   `questions` AS `questions` 
       LEFT OUTER JOIN `answers` AS `answers` 
                    ON `questions`.`id` = `answers`.`question_id` 
WHERE  `questions`.`id` NOT IN ( -1 ) 
ORDER  BY `questions`.`id` ASC, 
          `answers`.`id` ASC 

And results in:

id  |   question    |   answers.id  |   answers.question_id |   answers.answer
13  |   first question  |   17  |   13  |   1st answer
13  |   first question  |   23  |   13  |   2nd answer
13  |   first question  |   24  |   13  |   3rd answer
14  |   second question |   18  |   14  |   1st answer
14  |   second question |   21  |   14  |   2nd answer
14  |   second question |   22  |   14  |   3rd answer
15  |   third question  |   19  |   15  |   1st answer
15  |   third question  |   20  |   15  |   2nd answer

I would like this result, but with the question sorted randomly.

So instead of 13, 14 then 15, it could be 14, 15, 13, but with answers still aligned with their question and sorted by answers.id.

Would appreciate any pointers for the Sequelize code or MySQL query to get such a result. Thanks!

I've tried adding ORDER BY RAND() in various places but it ends up shuffling the answers as well.

P.S. As an aside, earlier I needed this with just one question picked randomly, for which I used:

SELECT `questions`.`id`       AS `question_id`, 
       `questions`.`question` AS `question`, 
       `answers`.`id`         AS `answer_id`, 
       `answers`.`answer`     AS `answer` 
FROM   (SELECT `questions`.`id`, 
               `questions`.`question` 
        FROM   `questions` AS `questions` 
        WHERE  (SELECT `question_id` 
                FROM   `answers` AS `answers` 
                WHERE  `questions`.`id` = `answers`.`question_id` 
                       AND questions.id NOT IN ( -1 ) 
                LIMIT  1) IS NOT NULL 
        ORDER  BY RAND() 
        LIMIT  1) AS `questions` 
       INNER JOIN `answers` AS `answers` 
               ON `questions`.`id` = `answers`.`question_id` 
ORDER  BY `answers`.`question_id`, 
          `answers`.`id` 

Which would return, e.g.:

id  |   question    |   answers.id  |   answers.question_id |   answers.answer
14  |   second question |   18  |   14  |   1st answer
14  |   second question |   21  |   14  |   2nd answer
14  |   second question |   22  |   14  |   3rd answer
like image 761
firasd Avatar asked Feb 23 '16 15:02

firasd


1 Answers

In plain MySQL:

SELECT  ...
    FROM  
      ( SELECT  RAND() AS rnd, id FROM questions ) AS r
    JOIN  questions AS q ON q.id = r.id
    JOIN  answers AS a   ON a.question_id = q.id
    ORDER BY  r.rnd, a.id
like image 163
Rick James Avatar answered Oct 05 '22 09:10

Rick James