从具有复杂结构的松散相关表中抓取 MySQL 计数

Grabbing MySQL counts from loosely related tables with complex structure

MySQL 这里。我在问答数据库中有以下数据模型:

[questions]
===
question_id : PK           # ex: 12345
question_value : VARCHAR   # ex: 'What is your favorite food?'

[answers]
===
answer_id : PK              # ex: 23456
question_id : FK            # points to a questions.question_id
answer_value : VARCHAR      # ex: 'Pizza', 'French Fries', etc.

[user_answers]
===
user_answer_id : PK         # ex: 34567
question_id : FK            # points to a questions.question_id
user_answer_value : VARCHAR # ex: 'Pizza', 'French Fries', etc.

...其中 [questions] 是一个 table 包含我将问用户的所有问题,[answers] 是一个 table 包含所有 每个问题的可能 个答案,[user_answers] 是用户针对特定问题给出的 实际 答案。因此,该应用程序使用 [questions][answers] 来呈现 user 以及问题和可能的答案,然后用户选择其中一个答案,并将结果写入 [user_answers] table.

一个非常重要需要注意的是,应用程序将保证永远不会有任何“孤儿”[user_answers],也就是说,始终[answers] 记录,其 [answer_value] 匹配 [user_answers.user_answer_value]。因此,如果在特定 question_id 下的数据库中有一个 [user_answers.user_answer_value],那么 总是 是一个匹配的 [answers.answer_value]。因此,在查询中将两个“值字段”相互匹配是安全的,不会丢失任何数据。

我意识到这不是一个很好的数据模型。但是关键指出我根本无法改变它;它被锁定并且超出了我进行更改的能力,我只是坚持使用它。不幸的是,尽管我愿意,但我不能接受任何需要更改数据模型的答案。

现在,我正在尝试编写一个 SQL 查询,对于给定的 question_id - return 以下列:

  1. answers.answer_idid
  2. answers.answer_value作为answer
  3. a count 有多少 user_answers 存在于特定 answers.answer_id,使用值字段作为确定匹配的方式(即“'Pizza' == 'Pizza'"), 如 popularity

因此使用上面的“最喜欢的食物”示例,假设这是数据库中唯一的问题,三个可能的答案是“披萨”、“炸薯条”和“芝士汉堡”。假设有 50 个用户回答了“披萨”,65 个用户回答了“炸薯条”,还有 12 个用户回答了“芝士汉堡”。然后查询将 return 结果如下:

id      |     answer      |   popularity
==========================================
123     |   Pizza         |   50
456     |   French Fries  |   65
789     |   Cheeseburgers |   12

重要提示:如果某个答案从未被任何用户选择过,那么它的计数应该为零 (0)。

到目前为止,我对此查询的最佳尝试是:

SELECT
  a.answer_id as id,
  a.answer_value as answer,
  count(ua.answer_id) as popularity
FROM
  answers a
INNER JOIN
  user_answers ua
ON
  a.question_id = ua.question_id
WHERE
  a.question_id = ?   # provided by application
  AND
  a.answer_value = ua.answer_value

但是我觉得这不对。一方面,我认为 INNER JOIN 不合适。我也相信我需要做一个 GROUP BY 但我不确定哪个 table/column 来对计数进行分组。

重要的是要注意,实际上这个数据库中会有数百个问题,每个问题有 4 - 8 个答案,并且会有数百(可能是数千)用户提供答案,所以这个查询很重要(它为每个问题的答案提供流行度计数)仅包括用户答案匹配与相同“父”问题 ID 相关的答案的计数。 谁能看出我哪里出错了?

我想这很简单:

SELECT answers.answer_id, answers.answer_value, COUNT(user_answers.user_answer_id)
FROM answers
LEFT JOIN user_answers ON answers.answer_value = user_answers.user_answer_value
WHERE answers.question_id = ?
GROUP BY answers.answer_id, answers.answer_value

LEFT JOIN 确保包含零计数。

PS:数据库设计有问题。我宁愿将其更改为 user_answers(user_answer_id, answer_id).

这将满足您的要求

select a.answer_id as id,a.answer_value as answer,count(user_answer_value) as popularity from user_answers ua 
join answers a on a.answer_id = ua.user_answer_value where a.question_id= 1 
group by a.answer_id, a.answer_value order by count(user_answer_value) desc