如何修复此查询?

时间:2011-07-15 16:48:39

标签: mysql sql

我正在编写一个人们提问的应用程序,并以调查的形式获得答案。每个问题都有2个选项,加上默认选项。当一个人回答问题时,他们可以选择提问者设定的2个选项,或者我选择的默认选项。例如,如果问题是香草与巧克力,选项将是香草,巧克力和两者。我希望能够将为问题选择的选项百分比制成表格,即25%说巧克力,30%说香草,45%不说。

我将首先显示表结构和我正在运行的查询。

这些是涉及的表(注意:这些不是完整的表结构):

--questions--
id
user_id
topic
description

--options--
id
text
default (bool)

--questions_options--
question_id
option_id

--answers--
id
question_id
user_id
option_id

以下是查询:

SELECT 
options.id AS option_id, options.text, options.default, 
ROUND( 
  IFNULL( 
    (COUNT(answers.option_id) * 100) 
    / 
    (SELECT COUNT(answers.option_id) FROM answers WHERE question_id = QUESTION_ID) 
  , 0) 
, 2) AS percentage 
FROM options 
LEFT JOIN questions_options ON questions_options.option_id = options.id 
LEFT JOIN answers ON answers.option_id = options.id 
WHERE questions_options.question_id = QUESTION_ID 
OR options.default = '1' 
GROUP BY options.id 
ORDER BY percentage DESC, option_id ASC

其中QUESTION_ID是整数常量。

问题是查询不仅仅限制针对特定问题的答案的答案,而且由于选项有很多问题,我得到的结果如600% for vanilla (如果多个问题使用香草作为选项)。如果选项对于一个问题是唯一的,那么百分比是有意义的,除了默认选项,所有问题都存在。我尝试将WHERE answers.question_id = QUESTION_ID放在那里,但它没有用。

任何解决方案?

由于

2 个答案:

答案 0 :(得分:0)

我可以看到的问题:

  • GROUP BY options.id表示您获得了options.textoptions.default的随机值。这可能会也可能不会改变您的结果,具体取决于您的数据结构。如果每id行有多行,则数据不准确或会产生误导。

  • 您的除数有WHERE条款,但百分比计算中没有您的红利 - 这意味着您的红利数量永远不会更低。尝试将WHERE question_id = QUESTION_ID放入第一个COUNT语句。

答案 1 :(得分:0)

你正在以错误的方向进行连接 - 你首先要查看选项,即使你已经明确表示你想要用问题列表的东西。这意味着您将获得所有选项的结果,无论它们是否与您的问题相关...... 哦,我假设answer_id已映射到question_id,或者您无法获得任何有意义的结果(也就是说 - 答案不是否则映射到问题...)

请尝试此查询:

SELECT b.id, b.text, b.default, (SELECT IFNULL(
                                           ROUND((COUNT(c.id) * 100) / 
                                                    (SELECT COUNT(d.id)
                                                     FROM answers as d
                                                     WHERE d.answer_id = a.question_id)
                                                 , 2)
                                               , 0)
                                 FROM answers as c
                                 WHERE c.answer_id = a.question_id
                                 AND c.option_id = a.option_id) as percentage

FROM questions_options as a
JOIN options as b
ON b.id = a.option_id
WHERE a.question_id = QUESTION_ID
ORDER BY percentage DESC, a.option_id ASC

请注意,我没有MySQL的副本来执行此操作,我通常会使用CTE(我已被告知MySQL不支持)。

<小时/> 编辑:

鉴于“默认”选项可能无法通过questions_options表进行映射,请尝试以下操作:

SELECT a.id, a.text, a.default, IFNULL(
                                       ROUND((b.answerCount * 100) / 
                                                     (SELECT COUNT(c.id)
                                                      FROM answers as c
                                                      WHERE c.answer_id = QUESTION_ID)
                                             , 2)
                                       , 0)                                            

FROM options as a
LEFT JOIN (SELECT c.option_id, count(c.id) as answerCount
           FROM answers as c
           WHERE c.question_id = QUESTION_ID
           GROUP BY c.option_id) as b
ON b.option_id = a.id

请注意,对于调查受访者的每个“默认”答案,您仍然会得到“毫无意义”的“0”结果 - 并且无法将这些与任何实际区别开来'0'会显示 向受访者提供的“默认”答案的结果。您可能更好地在questions_options表中放置所谓的“默认”选项 - 实际上,您无法确定所有提交给受访者的选项(您可以回答哪些选项,这是完全不同的);对您的公司而言,这可能是一个巨大的业务责任问题。此外,一些“默认”选项在上下文中可能没有意义 - “你喜欢你的茶还是冷的”,“是的”。