sql >> Base de Datos >  >> RDS >> Mysql

mysql sql complicado

Este es otro ejemplo de un TOP X registros por Y ejemplo. Para cada pregunta, quieres 4 respuestas. En realidad, se necesita un LÍMITE DOS VECES... Primero para limitar las preguntas de calificación, y otra "clasificación" de respuestas que garantiza que la respuesta "Correcta" SIEMPRE se incluya por conjunto de resultados de preguntas.

Así que mi enfoque es aplicar las preguntas aleatorias en contra primero para obtener eso como un resultado de subconjunto, luego unirlo a las respuestas y limitar X por Y. LUEGO, podemos terminarlo todo. Lo fundamental aquí es que la consulta interna debe ordenarse por el ID de la pregunta... Y el calificador de la respuesta "Correcta" siempre está en la primera posición, pero todo lo que sigue se aleatoriza para incluir un total de 4 registros.

Luego, la consulta final aplica la cláusula WHERE para incluir solo donde la secuencia de clasificación es <=4 (de las 9 respuestas posibles incluidas para 1 pregunta, pero luego aplica una cláusula final "ORDER BY" para mantener las preguntas juntas, pero aleatoriza las respuestas para que el "Correcto" ya no se devuelva siempre en la primera posición. Puede eliminar esta cláusula externa "ORDER BY" con fines de prueba solo para confirmar la funcionalidad y luego volver a agregarla más tarde.

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 par de pequeños cambios... Asegúrate de SQLVars tiene := para cada una de las tareas. Cuando publiqué originalmente, dejé un ":" que podría haber arrojado un error falso. También califiqué el "Ordenar por" interno usando "a.correct =1" (no tenía referencia de alias). Finalmente, cambió la cláusula WHERE externa a solo < 5 en lugar de <= 4 . He hecho MUCHAS de estas grandes agrupaciones X por Y y sé que funcionan, solo me falta algo simple, estoy seguro.

Además, ajustó el IF() aleatorio para tener el primer valor como un decimal, de lo contrario, todos los aleatorios se establecen en 1 (número entero) y nunca en fracciones ... También para posibles problemas de cuándo se aplica el ORDEN, he consultado previamente todas las preguntas y respuestas ordenadas previamente para obtener todas las respuestas correctas en la primera posición, ENTONCES aplique SQLVars contra ese conjunto, luego finalice la secuencia de clasificación y el orden.