Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select multiple fields in the same row? (MySQL)

Tags:

php

select

mysql

I asked a question yesterday about using MySQL to tally results to a survey.

Now my question is, if I had a table of survey questions, a table of survey choices, and a table of users answers to those survey questions, how would I select the survey question along with all the choices for that survey within the same query?

Questions Table

question_id (int)
question (text)

Choices Table

choice_id (int)
question_id (int)
choice_text (varchar)

Answers Table

answer_id (int)
question_id (int)
choice_id (int)

What SELECT should I do to get the survey question along with all the choices for that survey (known or unknown amount) all in the same query? (if possible, also do the math, found in my other question, within the same query)

I'm not so advanced with MySQL.

Thanks

EDIT: Sorry, What I meant was, I'm trying to get a SELECT statement to select the question, and all the choices corresponding to that question, in one row.

If I do something like

SELECT question_id, question, choice_id, choice_text FROM questions LEFT JOIN choices USING(question_id)

I get multiple rows, one for each choice_id.

The results should be something like

question     choice_1  choice_2  choice_3
A or B or C     A          B        C

The math part is tallying up the results to the survey, and yes, the choice_id is a PK, if that helps.

like image 888
BDuelz Avatar asked Jan 22 '10 22:01

BDuelz


People also ask

How to select multiple rows in one query with multiple conditions?

mysql - Selecting Multiple Rows in One Query with Multiple Conditions - Database Administrators Stack Exchange I can select multiple rows with one condition by using something like: SELECT `Col`, `Col2` FROM `Table` WHERE `Col3` IN (?, ?, ?, ?, ?);

How to handle a subquery that returns multiple rows in MySQL?

You may use the IN, ANY, or ALL operator in outer query to handle a subquery that returns multiple rows. IN operator is used to checking a value within a set of values. The list of values may come from the results returned by a subquery. See the following example :

How many rows can I select in a single query?

A single query will select from 10 to 100 rows (though most of the time it'll be only 10)- it has to be fast in terms of performance. This is why using multiple queries isn't a good idea. The CREATE TABLEstatement is:

Is there a way to get multiple columns from a subquery?

Is there a way to get multiple columns from a single subquery or should I use two subqueries (MySQL is smart enough to group them?) or is joining the following way to go: [ [attribute to language] to translation] (joining 3 tables seems like a worse performance than subquery). Show activity on this post. Yes, you can do this.


1 Answers

To get the questions and the choices for each question:

SELECT question, choice_text
FROM questions
JOIN choices
ON questions.question_id = choices.question_id

Add LEFT before JOIN if you also want questions that have no choices.

To get the counts for each answer you could do this:

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

To get the number of people that selected each answer as a percentage (per question) use the following query:

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;

Here's the testdata I used:

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);

And the output I get with the last query on this data:

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

In the update to your question you say you want to return all the values for one question on one row. I would recommend that you do not try to do this, and instead use the method I have given you above. If you need to present the data in one row to your end-user, this can be done using PHP.

like image 181
Mark Byers Avatar answered Oct 18 '22 11:10

Mark Byers