Mysql
 sql >> Datenbank >  >> RDS >> Mysql

mysql kompliziertes sql

Dies ist ein weiteres Beispiel für ein Beispiel für die TOP X Datensätze pro Y. Für jede Frage möchten Sie 4 Antworten. EIN LIMIT wird tatsächlich ZWEIMAL benötigt ... Erstens, um die qualifizierenden Fragen einzuschränken, und eine weitere "Rangfolge" der Antworten, die garantiert, dass die "richtige" Antwort IMMER pro Frageergebnissatz enthalten ist.

Mein Ansatz ist also, zuerst die zufälligen Fragen gegen Fragen anzuwenden, um das als Teilmenge zu erhalten, dann das mit den Antworten zu verbinden und X pro Y zu begrenzen. DANN können wir alles einpacken. Das Entscheidende hier ist, dass die innere Abfrage nach der Fragen-ID sortiert werden muss ... UND der Qualifizierer, die "richtige" Antwort, steht immer an erster Stelle, aber alles danach wird zufällig ausgewählt, um insgesamt 4 Datensätze einzuschließen.

Dann wendet die letzte Abfrage die WHERE-Klausel an, um nur einzuschließen, wo die Rangfolge <=4 ist (von den möglichen alle 9 Antworten, die für 1 Frage enthalten sind), wendet dann aber eine abschließende "ORDER BY"-Klausel an, um die Fragen zusammenzuhalten, aber randomisiert die Antworten, sodass das "Richtig" nicht mehr immer an erster Stelle zurückgegeben wird. Sie können diese äußere "ORDER BY"-Klausel zu Testzwecken entfernen, nur um die Funktionalität zu bestätigen, und sie später wieder hinzufügen.

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

Ein paar kleine Änderungen... Achten Sie auf die SQLVars hat := für jede der Aufgaben. Als ich ursprünglich gepostet habe, habe ich ein ":" weggelassen, was einen falschen Fehler hätte auslösen können. Ich habe auch das innere "Order by" qualifiziert, indem ich "a.correct =1" verwendet habe (hatte keine Alias-Referenz). Schließlich wurde die äußere WHERE-Klausel in nur < 5 geändert statt <= 4 . Ich habe VIELE dieser großartigsten X-per-Y-Gruppierungen gemacht und weiß, dass sie funktionieren, nur etwas Einfaches fehlt, da bin ich mir sicher.

Passen Sie auch IF() an random, um den ersten Wert als Dezimalzahl zu haben, andernfalls werden alle Randoms auf 1 (ganze Zahl) und niemals Bruch gesetzt ... Auch für mögliche Probleme bei der Anwendung der ORDERING habe ich alle Q und A vorsortiert vorab abgefragt Um alle richtigen Antworten an erster Stelle zu erhalten, wenden Sie DANN die SQLVars an gegen diesen Satz, dann schließen Sie die Rangfolge und Reihenfolge ab.