Как мне исправить этот запрос? - PullRequest
0 голосов
/ 15 июля 2011

Я пишу приложение, в котором люди задают вопросы и получают ответы в форме опроса.Каждый вопрос имеет 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 голосов
/ 15 июля 2011

Вы делаете соединения в неправильном направлении - сначала вы смотрите на опции , даже если вы специально заявили, что хотите, чтобы все было сведено в таблицу с помощью question . Это означает, что вы получаете результаты для всех вариантов, независимо от того, относятся ли они даже к вашему вопросу ...
О, и я предполагаю, что 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 - так как у вас нет возможности определить все параметры, которые были представили респондентам (какие из них у вас есть ответы, а какие совсем другие); это может быть огромной проблемой для вашей компании. Кроме того, некоторые параметры «по умолчанию» могут не иметь смысла в контексте: «Предпочитаете ли вы чай горячим или холодным», «Да».

0 голосов
/ 15 июля 2011

Проблемы, которые я вижу:

  • Вы GROUP BY options.id, что означает, что вы получаете случайные значения для options.text и options.default.Это может или не может изменить ваши результаты в зависимости от структуры ваших данных.Если в id есть несколько строк, то это будут неточные или вводящие в заблуждение данные.

  • У вас есть условие WHERE для вашего делителя, но не ваш дивиденд в расчете процента - этоозначает, что вы никогда не будете иметь меньший счет для дивидендов.Попробуйте вставить WHERE question_id = QUESTION_ID в первый оператор COUNT.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...