Выберите и подсчитайте голоса из таблицы опроса, где не все варианты имеют голоса - PullRequest
1 голос
/ 29 ноября 2011

Я борюсь с задачей, которая может быть очень простой, но мне трудно ее понять. У меня есть две таблицы базы данных:

options_table

option_id | option_name | question_id |
    1     |   opt one   |      4      |
    2     |   opt two   |      4      |
    3     |   opt three |      4      |
    4     |   opt four  |      4      |

и voice_table

question_id | survey_id | option_id |
    4       |    1      |     1     |
    4       |    1      |     2     |
    4       |    1      |     2     |
    4       |    1      |     1     |
    4       |    1      |     3     |
    4       |    1      |     2     |

Из этого примера у нас есть 2 голоса по варианту 1, 3 голоса по варианту 2 и 1 голос по варианту 3, но ни одного по варианту 4 Я хотел бы получить название всех опций с относительным количеством, но я не могу получить опцию без голосов. Я уверен, что я что-то упускаю, это конец рабочего дня, и я должен быть уставшим. Я пробовал что-то вроде:

   SELECT o.option_name, count(*) as cnt 
   FROM votes_table AS v 
   JOIN options_table AS o 
   ON o.option_id = v.option_id 
   WHERE v.survey_id = 1 
   GROUP BY o.option_name

но я просто получаю

option_name | option_id | cnt
 opt one    |   1       |  2
 opt two    |   2       |  3
 opt three  |   3       |  1

Как мне получить также "опт четыре"? Поэтому я могу правильно отобразить все результаты опроса, включая опцию, за которую никто не голосовал. Я также пытался использовать OUTER JOIN, но безрезультатно.

Мне стыдно за это, может показаться глупым вопросом, но мне еще многое предстоит узнать о базах данных и отношениях

Ответы [ 4 ]

1 голос
/ 29 ноября 2011

Используйте LEFT вместо INNER объединение - поместите в левой части таблицы все параметры, а в правой части таблицы пропущенные параметры.

Переместите любое условие, в котором используется столбец из правой таблицы, например v.survey_id = 1, из условия WHERE в ON.

Используйте COUNT(RightTable.column) вместо COUNT(*), так что вы получите 0 для опций без голосования:

SELECT o.question_id
     , o.option_name
     , COUNT(v.option_id) as cnt 
FROM 
    options_table AS o  
  LEFT JOIN 
    votes_table AS v
      ON  v.option_id = o.option_id 
      AND v.question_id = o.question_id
      AND v.survey_id = 1 
WHERE o.question_id = 4            --- if you want results for one question only 
GROUP BY o.question_id
       , o.option_id

Я полагаю, что (option_id, question_id) - это первичный (или уникальный) ключ таблицы options. Вот почему вам нужно либо GROUP BY оба, либо WHERE o.question_id и GROUP BY o.option_id.

В противном случае, если вы только GROUP BY o.option_id, запрос для каждого варианта, будет подсчитывать голоса для всех вопросов, которые были выбраны с этим вариантом.

1 голос
/ 29 ноября 2011
SELECT 
  o.option_name, 
  ( SELECT 
      count(*) 
    FROM 
      votes_table 
    WHERE  
      v.survey_id = 1
    AND
      v.question_id = o.question_id
    AND
      v.otion_id = o.option_id 
  ) as cnt 
options_table AS o;
0 голосов
/ 29 ноября 2011

Попробуйте это

SELECT o.option_name, count(*) AS cnt 
FROM options_table o 
LEFT JOIN votes_table v ON o.option_id = v.option_id 
WHERE v.survey_id = 1 
GROUP BY o.option_name

Если вы используете INNER JOIN, вы получите только записи, имеющие соответствующий элемент в обеих таблицах.

0 голосов
/ 29 ноября 2011

Вместо использования INNER JOIN (JOIN) вы можете использовать LEFT JOIN для достижения этого

 SELECT o.option_name, count(*) as cnt 
 FROM options_table AS o  
 LEFT JOIN votes_table AS v
 ON o.option_id = v.option_id 
 WHERE v.survey_id = 1 
 GROUP BY o.option_name;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...