Reputation: 2399
I have a bit of a problem. I have a database layout like so:
customer
customer_id, name, age, etc...
customer_survey_question
id, category, caption, type
customer_survey_answer
id, customer_id, customer_survey_question_id, answer
and I need to pull in their answers like so:
name, age, etc..., question 1, question 2, question 3, etc...
Now I could do a sub-query:
SELECT
`customer`.*,
(
SELECT `answer`
FROM `customer_survey_answer`
WHERE `customer_survey_answer`.`customer_id`=`customer`.`customer_id`
AND `id`=1
) AS `question_1`,
(
SELECT `answer`
FROM `customer_survey_answer`
WHERE `customer_survey_answer`.`customer_id`=`customer`.`customer_id`
AND `id`=2
) AS `question_2`,
....
But there is 14 questions and I need to be able to do this pretty quickly and expand up to 80+ questions. What is the best way to approach?
Upvotes: 0
Views: 83
Reputation: 28196
If you want to generate a table in a single query you could use the group by
on a query with a single INNER JOIN
and then collect the values in several MAX( CASE ... END )
expressions. Sounds complicated at first but it does work reliably (just add another line for each desired column):
SELECT name, age,
MAX(CASE WHEN customer_survey_question_id=1 THEN answer END) a1,
MAX(CASE WHEN customer_survey_question_id=2 THEN answer END) a2,
MAX(CASE WHEN customer_survey_question_id=3 THEN answer END) a3,
MAX(CASE WHEN customer_survey_question_id=4 THEN answer END) a4,
MAX(CASE WHEN customer_survey_question_id=5 THEN answer END) a5,
MAX(CASE WHEN customer_survey_question_id=6 THEN answer END) a6,
MAX(CASE WHEN customer_survey_question_id=7 THEN answer END) a7,
MAX(CASE WHEN customer_survey_question_id=8 THEN answer END) a8,
...
FROM customer c INNER JOIN customer_survey_answer s
ON s.customer_id=c.customer_id
Upvotes: 0
Reputation: 410
It is not wise to force DB output into result's columns.
In case you would like to operate over one only customer, make simple question query and then answer query to get everything and put it together outside of DB - in PHP for example.
In case you would like the list of customers with their answers, make first the question query and then make the "answer x customer" query with respective ids and put them together using hashing outside the DB. It works well and fast unless you don't use paging for your output list ;).
Hash can work like this
// suppose we have from database
// $answer_list(id,customer_id,customer_name,question_id,answer)
// $question_list(id,question)
// hash
$customer_list = array();
$customer_hash = array();
foreach ($answer_list as $answer)
{
$customer_id = $answer['customer_id'];
if (!isset($customer_hash[$customer_id]))
{
$customer_list[] = $customer_id;
$customer_hash[$customer_id]['name'] = $answer['customer_name'];
}
$customer_hash[$customer_id]['answer_hash'][$answer['question_id']] = $answer;
}
// output
foreach ($customer_list as $customer_id)
{
echo $customer_hash[$customer_id]['id'];
echo $customer_hash[$customer_id]['name'];
foreach ($question_list as $question)
{
echo $question['question'];
echo $customer_hash[$customer_id]['answer_hash'][$question['id]]['answer'];
}
}
Upvotes: 0
Reputation: 6148
You cannot do this through a query by and of itself.
Look here for some example code: How to merge data from 2 tables with MySQL
What you can do is use an INNER JOIN
or GROUP_CONCAT
and then reformat the data in your script (whether that be php
or another language)
Unser the circumstances this would likely lead to a large excess/irrelevant data in each row
SELECT c.*, csa.answer
FROM customers c
INNER JOIN
customer_survey_answer csa ON csa.`customer_id`=c.`customer_id`
ORDER BY c.customer_id, csa.customer_survey_question_id
This will output one cell (csv style) as the answers
SELECT c.*, GROUP_CONCAT(csa.answer) as answers
FROM customers c
INNER JOIN
customer_survey_answer csa ON csa.`customer_id`=c.`customer_id`
GROUP BY c.customer_id
You might also consider querying the database for a list of customers with answers and then running a second query (for each customer returned) to get their answer. This could lead to a large number of queries.
First query:
SELECT * FROM customers
Second query:
SELECT answer
FROM customer_survey_answer
WHERE customer_id = INSERT_CUSTOMER_ID_HERE}
Upvotes: 1
Reputation: 18550
you want to pivot the data
SELECT class,GROUP_CONCAT(member)
FROM tbl
GROUP BY class;
is the basic case
http://www.artfulsoftware.com/infotree/queries.php#78
Upvotes: 0