Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is another example of a TOP X records per Y example. For every question, you want 4 answers. A LIMIT is actually needed TWICE... First to limit the qualifying questions, and another "ranking" of answers which guarantees the "Correct" answer to ALWAYS be included per question result set.</p> <p>So my approach is to apply the random against questions first to get that as a subset result, then join that to the answers and limit X per Y. THEN, we can get it all wrapped up. The critical thing here is the inner query has to be ordered by the question ID... AND the qualifier the "Correct" answer is always in first position, but anything after is randomized to include a total of 4 records.</p> <p>Then, the final query applies the WHERE clause to only include where the ranking sequence is &lt;= 4 (of the possible all 9 answers included for 1 question, but then applies a final "ORDER BY" clause to keep the questions together, but randomizes the answers so the "Correct" is no longer always returned in the first position. You can remove this outer "ORDER BY" clause for testing purposes just to confirm functionality, then add it back in later.</p> <pre><code>select FinalQA.* from ( select QWithAllAnswers.*, @RankSeq := if( @LastQuestion = QWithAllAnswers.id, @RankSeq +1, 1 ) ARankSeq, @LastQuestion := QWithAllAnswers.id as ignoreIt from ( SELECT q.id, q.question, q.RandQuestionResult, a.question_id, a.answer, a.correct FROM ( SELECT q.ID, q.Question, q.question_ID, RAND() as RandQuestionResult FROM questions q WHERE q.subject_id = 18 ORDER BY RAND() LIMIT 5) JustQ JOIN answers a on q.id = a.question_id ORDER BY JustQ.RandQuestionResult, if( a.correct = 1,0.000000, RAND() ) QWithAllAnswers, ( select @RankSeq := 0, @LastQuestion := 0 ) SQLVars ) FinalQA where FinalQA.ARankSeq &lt; 5 order by FinalQA.RandQuestionResult, rand() </code></pre> <p>Couple small changes... Make sure at the <code>SQLVars</code> has <code>:=</code> for each of the assignments. When I originally posted, I left one ":" off which could have thrown a false error. I also qualified the inner "Order by" by using "a.correct = 1" (had no alias reference). Finally, changed the outer WHERE clause to just <code>&lt; 5</code> instead of <code>&lt;= 4</code>. I've done MANY of these greatest X per Y groupings and know they work, just missing something simple I'm sure.</p> <p>Also, adjusted the <code>IF()</code> random to have first value as a decimal, otherwise all randoms get set to 1 (whole number) and never fraction... Also for possible issues of when the ORDERING is applied, I've pre-queried all Q and A pre-sorted to get all Correct answers in the first position, THEN apply the <code>SQLVars</code> against that set, then finalize the rank sequence and ordering.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload