如何使这个查询更容易编写

时间:2009-01-09 22:03:25

标签: mysql optimization

我有一个查询从一个表中提取问题并从另一个表中提取答案。

SELECT 
  questions.question, 
  questions.answers, 
  (SELECT COUNT(answer) FROM answers WHERE question_id = 1 AND answer = 1 
          GROUP BY answer) as ans1, 
  (SELECT COUNT(answer) FROM answers WHERE question_id = 1 AND answer = 2 
          GROUP BY answer) as ans2 
FROM questions 
WHERE questions.id = 1

虽然这有效但我不喜欢为每个答案添加额外的子查询(questions.answers是一个逗号分隔的潜在答案字符串)。它是可行的,但我敢肯定必须有更好的方法。主要的是,不同的问题有不同的答案数量。

有更好的方法可以做到这一点,还是这是一种可接受的做事方式?我认为查询中的多个子选择将来可能会有(小)性能损失(而不是我的性能测试)。

如果适用,我不希望每个问题有超过5个答案。

6 个答案:

答案 0 :(得分:8)

SELECT q.question, q.answers,
  SUM(a.answer = 1) AS ans1,
  SUM(a.answer = 2) AS ans2
FROM questions q
 LEFT OUTER JOIN answers a ON (q.id = a.question_id)
WHERE q.id = 1
GROUP BY q.id;

答案 1 :(得分:2)

对我来说看起来很不错。您可以在子查询中省略“group by”子句,因为您只选择了一个“answer”值。

我怀疑,如果要保存每个答案的可能答案列表,那么您的架构可能会出现问题。这可能应该在一个单独的表中,每个答案由一行表示。在数据库设计中,分隔符分隔的字符串是一个很大的代码气味,你期望它们的数据重复。

答案 2 :(得分:1)

可能?

SELECT 
    questions.question, 
    questions.answers, 
    (case when answers.answer = 1 then COUNT(answer) end ) as ans1, 
    (case when answers.answer = 2 then COUNT(answer) end ) as ans2 
    FROM questions left join answers on answers.question_id = questions.id
    WHERE questionss.id = 1
    group by questions.id

答案 3 :(得分:0)

你能用吗?

SELECT 
  questions.question, 
  questions.answers, 
  COUNT(answer)

FROM questions inner join answers
on questions.id = answer.question_id
WHERE questions.id = 1
GROUP BY
questions.question, 
questions.answers

你会获得行而不是列,但结果相似。

答案 4 :(得分:0)

将一个表中的多个行链接到另一个表中的一个或多个行的标准方法是使用链接表。这样的表会在每个行中存储一个表中的ID和另一个表中与第一个表相关的ID。

对于您的问题和答案,在链接表(我可能称之为question_answered)中存储问题的可能答案可能如下所示:

question_id | answer_id

1 1

1 2

2 3

4 4

4 5

4 6 `

如你所见,问题1有两个可能的答案,问题2有1个可能的答案,问题3没有答案,而问题4有3个不同的答案。

虽然我不确定“answer = 1”或“answer = 2”在您的上下文中是什么意思,但使用链接表计算问题的所有答案很容易:

SELECT question, count(answer_id) FROM questions AS q INNER JOIN question_answered AS qa ON qa.question_id = q.id) GROUP BY q.id

答案 5 :(得分:0)

      SELECT    questions.question,
                       questions.answers,
                       A.answer,
                       COUNT(A.answer)
        FROM      questions Q
LEFT JOIN      answers A
            ON      Q.id = A.question_id
     WHERE      questions.id = 1
          AND      A.answer IN (1,2)
GROUP BY     A.answer