任何人都可以告诉我为什么这个查询没有产生正确的答案

时间:2013-08-06 15:04:04

标签: sql sql-server-2008 sql-server-2005

史蒂夫·福特帮助我解决了下面这个问题。 (再次感谢史蒂夫)。

SELECT SUM(CASE WHEN SC.IsCorrect = 1 THEN 1 ELSE 0 END) AS TotalQuestions,
  COUNT(SA.AnswerID) AS TotalCorrect,
  CAST(COUNT(SA.AnswerID) AS Float) / 
  SUM(CASE WHEN SC.IsCorrect = 1 THEN 1 ELSE 0 END) * 100 As Percentage
  FROM SurveyQuestions SQ
  INNER JOIN SurveyChoices SC ON SQ.QuestionId = SC.QuestionID
  LEFT JOIN SurveyAnswers SA ON SA.QuestionId = SC.QuestionID 
  AND SA.ChoiceID = SC.ChoiceID
  AND SA.UserName = 'John.Doe'
  WHERE SC.IsCorrect = 1 
  AND SQ.SurveyID = 10

以下是他的小提琴演示。

http://sqlfiddle.com/#!3/4c642/1

该查询旨在以下列格式显示调查结果:

总问题: _ 总更正: _ 百分比正确 _

大部分都有效。

但是,它仍然无法正确处理复选框。

例如,SurveyQuestions表中有一个名为AnswerType的字段名称。

多个选项答案的值 M ,例如用户可以检查一个或多个框的复选框。 单个答案的 S ,例如单选按钮选项。在这里,用户只能选择一个答案。 最后,T代表Freetext,用户可以输入他们喜欢的任何值。

我们并不关心T answerType。

Steve的代码正确计算了Checkboxes的值。

还有另一个名为IsCorrect的字段。

任何正确的答案,无论是单选还是多项选择,其值都存储在isCorrect位数据类型中。

如果答案不正确,则isCorrect的值为0.

我在Steve的查询中看到的唯一问题是,如果值为isCorrect = 1,那么它会将其视为一个问题。

因此,如果您检查实例2复选框,并将其检查为正确答案,则Steve的代码会处理这两个单独的问题。

无论如何将M的answertYpe视为一个问题而不管检查了多少盒子作为正确的答案?

谢谢大家的帮助。

2 个答案:

答案 0 :(得分:1)

这是一个嵌套查询。最内部的查询是将问题连接到所有可能的答案,然后左连接到用户做出的实际选择。实际正确的可能答案的计数仅基于选择表,然后是答案表中的实际正确输入。我得到了一份正确的答案和一份提供的ACTUAL答案。这样,最终的“正确”答案是问题正确答案计数与用户的正确答案计数匹配...并且用户提供的答案总数相同。这将处理一个问题的实例,其中包含2个正确的答案和一个人选择3个选项,其中2个是正确的......所以2 = 2是正常的,但是当它与3个选项 - 用户OVER PICKED相比时会失败。如果用户只选择一个选项并且其中一个是正确的,那么也处理...因此无论有多少可能的正确答案可用,2 = 1都会失败。

分组是按问题进行的,所以那些单身的人只会有正确答案1和1可能正确答案(或不答案)。这个倍数将被汇总,因此它也只是一个输入问题。

然后我将这些总计推到一行FinalCorrectAnswers和TotalQuestions。

然后

SELECT
      FinalCorrectAnswers,
      TotalQuestions,
      ( FinalCorrectAnswers / ( 1.000 * TotalQuestions )) * 100.00 as Percentage
from
(
SELECT
      SUM( case when AnsByType.CorrectChoices = AnsByType.CorrectAnswers
                 AND AnsByType.CorrectChoices = AnsByType.TotalAnswersProvided
              then 1.000 else 0.000 end) as FinalCorrectAnswers,
      sum( 1 ) as TotalQuestions
   from
      ( SELECT 
              SQ.QuestionID,
              SUM( case when SCM.IsCorrect = 1 then 1 else 0 end ) as CorrectChoices,
              SUM( case when SCM.IsCorrect = 1 
                         AND NOT MAnswers.ChoiceID IS NULL
                      then 1 else 0 end ) as CorrectAnswers,
              COUNT( MAnswers.ChoiceID ) as TotalAnswersProvided
           from 
              SurveyQuestions SQ
                 Join SurveyChoices SCM
                    ON SQ.QuestionID = SCM.QuestionID
                    LEFT JOIN SurveyAnswers MAnswers
                       ON SCM.QuestionID = MAnswers.QuestionID
                       AND SCM.ChoiceID = MAnswers.ChoiceID
                       AND MAnswers.UserName = 'John.Doe'
           where
              SQ.SurveyID = 10
           group by
              SQ.QuestionID ) AnsByType  ) FinalSum

基于来自SQLFiddle的示例数据,我认为正确答案是0%正确回答。如果您从答案中列出的同一样本集中运行this sqlfiddle,问题8只有一个选择答案,但用户没有输入该值。问题9是一个多项选择答案,但该人只回答了一个正确的答案。因此,由于BOTH没有得到正确回答,答案是错误的,因此答案都不正确且得分为零。

答案 1 :(得分:0)

所以我对你的逻辑不是100%肯定的,你如何处理有3个正确选择并且只选择其中2个的情况,或者如果只有2个正确选择并且总共选择3个,这会使问题不正确吗?

你必须决定这个逻辑,但我认为你需要逐个问题地查看你的数据,即检查有多少正确的选项,给出了多少正确的选项,然后你可以分析数据作为一个整体,唯一应该改变的逻辑是上述情景:

WITH Questions AS
(   SELECT  SQ.QuestionID,
            CorrectChoices = COUNT(NULLIF(SC.IsCorrect, 0)),
            ChoicesGiven = COUNT(SA.ChoiceID),
            CorrectChoicesGiven = COUNT(CASE WHEN SA.ChoiceID IS NOT NULL AND SC.IsCorrect = 1 THEN 1 END)
    FROM    SurveyQuestions SQ
            INNER JOIN SurveyChoices SC 
                ON SQ.QuestionId = SC.QuestionID
            LEFT JOIN SurveyAnswers SA 
                ON SA.QuestionId = SC.QuestionID 
                AND SA.ChoiceID = SC.ChoiceID
                AND SA.UserName = 'John.Doe'
    WHERE   SQ.SurveyID = 10
    GROUP BY SQ.QuestionID
)
SELECT  TotalQuestions = COUNT(*),
        TotalCorrect = COUNT(CASE WHEN CorrectChoicesGiven = CorrectChoices THEN 1 END),
        PercentCorrect = CAST(100.0 * COUNT(CASE WHEN ChoicesGiven = CorrectChoices THEN 1 END) / COUNT(*) AS DECIMAL(5, 2)),
        TotalCorrect2 = SUM(CorrectChoicesGiven),
        PercentCorrect = CAST(100.0 * SUM(CorrectChoicesGiven) / SUM(CorrectChoices) AS DECIMAL(5, 2))
FROM    Questions;

<强> Updated example on SQL Fiddle


修改

根据评论中的逻辑,对于在多项选择中错过的每个正确答案,分数按比例减少,类似于给出的任何错误答案,规则变为如下(在所有示例中,数字指的是一个多重问题,其中有3个可能的正确答案)

  • 如果给出的正确答案的数量与总数相符 答案,并没有选择不正确的答案,然后得分为100%

  • 如果给出的正确答案的数量与总数相符 答案,但给出了额外的错误答案然后得分 被错误的选择减少为总正确的百分比 选择(例如,当只有3个正确时,选择4个选项将减少 得分为1/3,得分为66.66%)

  • 如果答案的数量 给定超过了正确的答案数,而不是全部正确 找到答案(例如4个答案,只有2个正确),这个 将额外答案的分数降低1,将1分降低 错过正确答案,减少2/3,所以得分为33%

这整个方法可以简化为下面的等式(确保0是最低答案);

(Correct answers given - Extra answers given) / Total Correct answers 

这种方法的缺陷是,在一个有3个可能正确答案的问题中,如果用户给出3个不正确的选项,则用户可以得到一个正确且仍为0的分数。另一种更简单的方法是用户得分作为他们给出的更多选择和正确答案的百分比,因此在前面的例子中,用户将获得25%(4个选择中的1个正确答案),如果他们只选择了3个中的1个答案,这是正确的,他们仍然会得到33%,因为他们选择的答案数量少于正确数量。我已将此方法作为Score2和Percentage2包含在以下查询中,以便您可以做出选择

WITH Questions AS
(   SELECT  SQ.QuestionID,
            CorrectChoices = COUNT(NULLIF(SC.IsCorrect, 0)),
            ChoicesGiven = COUNT(SA.ChoiceID),
            CorrectChoicesGiven = COUNT(CASE WHEN SA.ChoiceID IS NOT NULL AND SC.IsCorrect = 1 THEN 1 END),
            ExtraChoicesGiven = CASE WHEN COUNT(SA.ChoiceID) > COUNT(NULLIF(SC.IsCorrect, 0)) THEN COUNT(SA.ChoiceID) - COUNT(NULLIF(SC.IsCorrect, 0)) ELSE 0 END
    FROM    SurveyQuestions SQ
            INNER JOIN SurveyChoices SC 
                ON SQ.QuestionId = SC.QuestionID
            LEFT JOIN SurveyAnswers SA 
                ON SA.QuestionId = SC.QuestionID 
                AND SA.ChoiceID = SC.ChoiceID
                AND SA.UserName = 'John.Doe'
    WHERE   SQ.SurveyID = 10
    GROUP BY SQ.QuestionID
), QuestionScores AS
(   SELECT  QuestionID,
            Score = CASE WHEN CorrectChoicesGiven - ExtraChoicesGiven < 0 THEN 0
                        ELSE CAST(CorrectChoicesGiven - ExtraChoicesGiven AS FLOAT) / CorrectChoices
                    END,
            Score2 = ISNULL(CAST(CorrectChoicesGiven AS FLOAT) / NULLIF(CASE WHEN ChoicesGiven > CorrectChoices THEN ChoicesGiven ELSE CorrectChoices END, 0), 0)
    FROM    Questions
)
SELECT  TotalQuestions = COUNT(*),
        TotalCorrect = SUM(Score),
        PercentCorrect = CAST(100.0 * SUM(Score) / COUNT(*) AS DECIMAL(5, 2)),
        TotalCorrect2 = SUM(Score2),
        PercentCorrect2 = CAST(100.0 * SUM(Score2) / COUNT(*) AS DECIMAL(5, 2))
FROM    QuestionScores;

<强> Updated SQL Fiddle