Mysql
 sql >> Base de données >  >> RDS >> Mysql

mysql sql compliqué

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.