如何在同一行中选择多个字段?(MySQL)

7
我昨天提出了一个问题,关于如何使用MySQL来统计调查结果。
现在我的问题是,如果我有一个调查问题的表格,一个调查选择的表格以及一个用户回答这些调查问题的表格,那么我该如何在同一查询中选择调查问题以及所有与该调查相关的选择?
问题表格
question_id (int)
question (text)

选择表格
choice_id (int)
question_id (int)
choice_text (varchar)

答案表
answer_id (int)
question_id (int)
choice_id (int)

我应该使用什么SELECT语句才能在同一查询中获取调查问题以及该调查的所有选项(已知或未知数量)?(如果可能,在同一查询中还要进行计算,见我其他问题)
我对MySQL不是很熟练。
谢谢
编辑:抱歉,我的意思是,我正在尝试获取一个SELECT语句来选择问题和与该问题对应的所有选项,放在同一行中。
如果我执行以下操作:
SELECT question_id, question, choice_id, choice_text FROM questions LEFT JOIN choices USING(question_id)

我得到了多行,每行对应一个choice_id。
结果应该是这样的:
question     choice_1  choice_2  choice_3
A or B or C     A          B        C

数学部分是对调查结果进行计算,是的,choice_id 是主键,如果这有帮助的话。

你只需要选项还是也需要计数?你的“其他问题”是什么,你想要做什么“数学”? - Mark Byers
你不是在寻找有关正确答案的任何信息吗?只是问题/选择可能性吗? - Evan Carroll
@Evan:这是一项调查,而不是测试——没有正确答案。 - Martha
你的数据库设计可能没有规范化。你的choice_id是主键吗?如果是,如果答案表中的question_id与choice_id的question_id不匹配会发生什么? - Mark Byers
你不能这样做。至少,你无法通过 php 获取它(你实际上可以使用 UNION() 但仍然无法正确获取它)。你可以选择问题,所有带有正确答案的选项,并将它们通过循环运行。当然,也可以处理多个问题。 - Kemo
我最初认为这是不可能完成的,但我还是想问一下。谢谢大家。 - BDuelz
4个回答

4
获取每个问题的问题和选项:
SELECT question, choice_text
FROM questions
JOIN choices
ON questions.question_id = choices.question_id

如果您还想获取没有选项的问题,可以在JOIN之前加上LEFT。
要获取每个答案的计数,您可以执行以下操作:
SELECT question, choice_text, COUNT(answers.choice_id)
FROM questions
JOIN choices
    ON questions.question_id = choices.question_id
LEFT JOIN answers
    ON questions.question_id = answers.question_id
    AND choices.choice_id = answers.choice_id
GROUP BY questions.question_id, choices.choice_id
ORDER BY questions.question_id, choices.choice_id

要获取每个答案选择人数的百分比(每个问题),请使用以下查询:
SELECT question, choice_text, COUNT(answers.choice_id) * 100 / questiontotal
FROM questions
JOIN (
        SELECT questions.question_id, COUNT(answers.choice_id) AS questiontotal
        FROM questions
        LEFT JOIN answers ON questions.question_id = answers.question_id
        GROUP BY questions.question_id
    ) AS answercounts
    ON questions.question_id = answercounts.question_id
JOIN choices ON questions.question_id = choices.question_id
LEFT JOIN answers
    ON questions.question_id = answers.question_id
    AND choices.choice_id = answers.choice_id
GROUP BY questions.question_id, choices.choice_id
ORDER BY questions.question_id, choices.choice_id;

以下是我使用的测试数据:
CREATE TABLE questions (question_id int, question nvarchar(100));
INSERT INTO questions (question_id, question) VALUES
(1, 'Foo?'),
(2, 'Bar?');

CREATE TABLE choices (choice_id int, question_id int, choice_text nvarchar(100));
INSERT INTO choices (choice_id, question_id, choice_text) VALUES
(1, 1, 'Foo1'),
(2, 1, 'Foo2'),
(3, 1, 'Foo3'),
(4, 2, 'Bar1'),
(5, 2, 'Bar2');

CREATE TABLE answers (answer_id int, question_id int, choice_id int);
INSERT INTO answers (answer_id, question_id, choice_id) VALUES
(1, 1, 1),
(2, 1, 1),
(3, 1, 3),
(4, 2, 4),
(4, 2, 5);

使用最后一个查询在这个数据上得到的输出:

'Foo?', 'Foo1', 66.6667
'Foo?', 'Foo2', 0.0000
'Foo?', 'Foo3', 33.3333
'Bar?', 'Bar1', 50.0000
'Bar?', 'Bar2', 50.0000

在更新问题时,您说您想在一行中返回一个问题的所有值。我建议您不要尝试这样做,而是使用我上面给出的方法。如果您需要将数据以一行的形式呈现给最终用户,可以使用PHP来实现。

3
我建议采用Mark Byers的答案,尽管理论上,如果您只是为了查看而不作为PHP例程的一部分需要将它们“全部放在一行中”,则可以执行此操作。
SELECT question, GROUP_CONCAT(choice_text) as choice_texts
FROM questions
JOIN choices
ON questions.question_id = choices.question_id
GROUP BY question;

输出结果将为:
'Foo?', 'Foo1,Foo2,Foo3'
'Bar?', 'Bar1,Bar2'

注意,'Foo1,Foo2,Foo3'将作为一列返回,而不是三列。GROUP_CONCAT默认情况下其输出的最大字符数为1024,尽管可以增加。如果结果可能很大,则不建议使用。


2
请注意,答案表可能不需要QuestionID列。
这将为您提供问题文本、选择文本以及每个选择的答案数量。
SELECT Questions.question, Choices.choice_text, Count(Answers.*) AS N
FROM Questions INNER JOIN Choices ON Questions.question_id = Choices.question_id
     LEFT JOIN Answers ON Choices.choice_id = Answers.choice_id
GROUP BY Questions.question_id, Choices.choice_id

编辑:除非你非常擅长SQL,否则最好忘记“全部一行”的部分 - 除非每个问题的选择数量不仅已知而且是恒定的,即使在这种情况下,也不容易。这实际上是一个显示问题,因此在显示结果时处理它。


我希望我能再点一个+1,因为你指出了不必要的QuestionID列。 - Mark Byers
很遗憾,你的查询似乎对我无效。我得到了“您的SQL语法错误;请检查与您的MySQL服务器版本相对应的手册以获取正确的语法说明,位置在第1行(*) AS N FROM Questions INNER JOIN Choices ON Questions.question_id = Choices.q”。 - Mark Byers
这可能是MySQL和其他SQL服务器语法差异造成的:尝试不使用“INNER”这个单词。(我的经验仅限于MS SQL Server。) - Martha

0
SELECT questions.question_id, questions.question, choices.choice_id, choices.question_id
FROM questions, choices 
WHERE questions.question_id = choices.question_id 
AND questions.question_id = "Something"

应该可以工作,我想。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接