Il s'agit d'un autre exemple d'un exemple TOP X d'enregistrements par Y. Pour chaque question, vous voulez 4 réponses. UNE LIMITE est en fait nécessaire DEUX FOIS... D'abord pour limiter les questions qualificatives, et un autre "classement" des réponses qui garantit que la réponse "correcte" sera TOUJOURS incluse par ensemble de résultats de question.
Donc, mon approche consiste à appliquer d'abord le hasard contre les questions pour obtenir cela en tant que résultat de sous-ensemble, puis à le joindre aux réponses et à limiter X par Y. ALORS, nous pouvons tout conclure. L'essentiel ici est que la requête interne doit être triée par l'ID de la question... ET le qualificatif de la réponse "correcte" est toujours en première position, mais tout ce qui suit est randomisé pour inclure un total de 4 enregistrements.
Ensuite, la requête finale applique la clause WHERE pour inclure uniquement où la séquence de classement est <=4 (sur les 9 réponses possibles incluses pour 1 question, mais applique ensuite une clause finale "ORDER BY" pour garder les questions ensemble, mais randomise les réponses afin que "Correct" ne soit plus toujours renvoyé en première position. Vous pouvez supprimer cette clause externe "ORDER BY" à des fins de test uniquement pour confirmer la fonctionnalité, puis la rajouter ultérieurement.
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()
Quelques petits changements... Assurez-vous que les SQLVars
a :=
pour chacune des missions. Lorsque j'ai posté à l'origine, j'ai laissé un ":" qui aurait pu générer une fausse erreur. J'ai également qualifié le "Order by" interne en utilisant "a.correct =1" (n'avait pas de référence d'alias). Enfin, changé la clause WHERE externe en juste < 5
au lieu de <= 4
. J'ai fait BEAUCOUP de ces plus grands groupements X par Y et je sais qu'ils fonctionnent, il manque juste quelque chose de simple, j'en suis sûr.
Aussi, ajusté le IF()
random pour avoir la première valeur sous forme décimale, sinon tous les randoms sont définis sur 1 (nombre entier) et jamais sur une fraction ... Aussi pour les problèmes éventuels de moment où le ORDERING est appliqué, j'ai pré-interrogé tous les Q et A pré-triés pour obtenir toutes les bonnes réponses en première position, ALORS appliquez les SQLVars
par rapport à cet ensemble, puis finalisez la séquence de classement et l'ordre.