Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL complicato sql

Questo è un altro esempio di record TOP X per Y esempio. Per ogni domanda, vuoi 4 risposte. In realtà è necessario UN LIMITE DUE VOLTE... Prima per limitare le domande qualificanti e un'altra "classifica" di risposte che garantisca che la risposta "Corretta" sia SEMPRE inclusa per set di risultati delle domande.

Quindi il mio approccio consiste nell'applicare prima le domande casuali per ottenerlo come risultato di un sottoinsieme, quindi unirlo alle risposte e limitare X per Y. POI, possiamo concludere tutto. La cosa fondamentale qui è che la query interna deve essere ordinata in base all'ID della domanda... E il qualificatore la risposta "Corretta" è sempre in prima posizione, ma qualsiasi cosa dopo viene randomizzata per includere un totale di 4 record.

Quindi, la query finale applica la clausola WHERE per includere solo dove la sequenza di classificazione è <=4 (delle possibili tutte e 9 le risposte incluse per 1 domanda, ma poi applica una clausola finale "ORDER BY" per tenere insieme le domande, ma randomizza le risposte in modo che "Corretto" non venga più sempre restituito nella prima posizione. Puoi rimuovere questa clausola esterna "ORDER BY" a scopo di test solo per confermare la funzionalità, quindi aggiungerla di nuovo in un secondo momento.

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()

Un paio di piccole modifiche... Assicurati in SQLVars ha := per ciascuno degli incarichi. Quando ho pubblicato originariamente, ho lasciato un ":" spento che avrebbe potuto generare un falso errore. Ho anche qualificato l'"Ordine per" interno usando "a.correct =1" (non aveva alcun riferimento alias). Infine, ho modificato la clausola WHERE esterna in solo < 5 invece di <= 4 . Ho creato MOLTI di questi migliori raggruppamenti X per Y e so che funzionano, mi manca solo qualcosa di semplice, ne sono sicuro.

Inoltre, regolato IF() random per avere il primo valore come decimale, altrimenti tutti i random vengono impostati su 1 (numero intero) e mai su una frazione... Anche per possibili problemi di quando viene applicato ORDERING, ho pre-interrogato tutte le Q e A pre-ordinate per ottenere tutte le risposte corrette nella prima posizione, ALLORA applica SQLVars rispetto a quel set, quindi finalizza la sequenza di classificazione e l'ordinamento.