Dit is weer een voorbeeld van een TOP X records per Y voorbeeld. Voor elke vraag wil je 4 antwoorden. Een LIMIET is eigenlijk TWEE KEER nodig... Eerst om de kwalificerende vragen te beperken, en een andere "rangschikking" van antwoorden die garandeert dat het "juiste" antwoord ALTIJD wordt opgenomen per vraagresultaatset.
Dus mijn benadering is om eerst de random tegen vragen toe te passen om dat als een subsetresultaat te krijgen, dat dan samen te voegen met de antwoorden en X per Y te beperken. DAN kunnen we het allemaal inpakken. Het cruciale punt hier is dat de innerlijke query moet worden geordend op de vraag-ID... EN de kwalificatie het "Correcte" antwoord staat altijd op de eerste positie, maar alles daarna wordt willekeurig verdeeld om in totaal 4 records op te nemen.
Vervolgens past de laatste query de WHERE-clausule toe om alleen op te nemen waar de rangschikkingsvolgorde <=4 is (van de mogelijke alle 9 antwoorden voor 1 vraag, maar past dan een laatste "ORDER BY"-clausule toe om de vragen bij elkaar te houden, maar randomiseert de antwoorden zodat de "Correct" niet langer altijd op de eerste positie wordt geretourneerd. U kunt deze buitenste "ORDER BY"-clausule voor testdoeleinden verwijderen om de functionaliteit te bevestigen, en deze later weer toevoegen.
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 < 5
order by
FinalQA.RandQuestionResult,
rand()
Paar kleine veranderingen... Zorg ervoor dat bij de SQLVars
heeft :=
voor elk van de opdrachten. Toen ik oorspronkelijk postte, liet ik een ":" weg die een valse fout had kunnen veroorzaken. Ik heb ook de innerlijke "Order by" gekwalificeerd door "a.correct =1" te gebruiken (had geen aliasreferentie). Verander ten slotte de buitenste WHERE-clausule in slechts < 5
in plaats van <= 4
. Ik heb VEEL van deze geweldige X per Y-groeperingen gedaan en weet dat ze werken, alleen mis ik iets eenvoudigs, dat weet ik zeker.
Pas ook de IF()
. aan willekeurig om de eerste waarde als decimaalteken te hebben, anders worden alle willekeurige getallen ingesteld op 1 (geheel getal) en nooit op breuken... Ook voor mogelijke problemen met het moment waarop de BESTELLING wordt toegepast, heb ik vooraf alle Q en A voorgesorteerd opgevraagd om alle juiste antwoorden op de eerste positie te krijgen, DAN pas de SQLVars
. toe tegen die set, voltooi vervolgens de rangorde en rangschikking.