I have written a query which transforms a couple of rows based on a condition into columns.
However, there are cases where no row meets the condition but I want to return some results.
Below is a sample of the table and the results I am looking for.
Source table:
id | respondent_id | demographic | question | answer |
---|---|---|---|---|
1 | 1 | checked | Age | 30 |
2 | 1 | null | education | masters |
3 | 1 | checked | height | 1.8m |
4 | 1 | null | income | $1 |
5 | 1 | null | address | ISS |
6 | 1 | null | talent | dancing |
7 | 2 | checked | Age | 20 |
8 | 2 | null | education | high school |
9 | 2 | checked | height | 4m |
10 | 2 | null | income | $3.2 |
11 | 2 | null | address | High sea |
12 | 2 | null | talent | singing |
Sample results after transformation:
id | respondent_id | Age | height | question | answer |
---|---|---|---|---|---|
2 | 1 | 30 | 1.8m | education | masters |
4 | 1 | 30 | 1.8m | income | $1 |
5 | 1 | 30 | 1.8m | address | ISS |
6 | 1 | 30 | 1.8m | talent | dancing |
8 | 2 | 20 | 4m | education | high school |
10 | 2 | 20 | 4m | income | $3.2 |
11 | 2 | 20 | 4m | address | High sea |
12 | 2 | 20 | 4m | talent | singing |
Current MySQL statement:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'(SELECT l.answer FROM source_table l where l.respondent_id = a.respondent_id AND l.question = ', b.question,')
AS ',b.question
)
) INTO @sql
FROM source_table b
WHERE b.demographic IS NOT NULL;
SET @sql =
CONCAT('SELECT respondents_id,
',@sql,',
a.question , a.answer
FROM source_table a
WHERE a.demographic IS NULL
GROUP BY id
');
PREPARE stmt FROM @sql;
EXECUTE stmt;
To clarify, the above query works when there are rows that are "checked" for the demographic column, however when there are no "checked" cells, the whole query fails.
So I would like a query that works under all conditions, whether there are demographic rows or not.
If there are no demographic rows, the query is supposed to return the data without the new columns
I'm a little confused on why you are using dynamic SQL. Window functions seems to do what you want:
select t.*
from (select t.*,
max(case when question = 'Age' then answer end) over (partition by respondent_id ) as age,
max(case when question = 'height' then answer end) over (partition by respondent_id ) as height
from source_table st
) t
where demographic is null;
I suppose you could use this as a template if you don't know the "checked" columns.
I think your goal is to generate a query like this:
SELECT respondent_id, a.question , a.answer,
(SELECT l.answer
FROM source_table l
WHERE l.respondent_id = a.respondent_id AND l.question = "Age") AS Age,
(SELECT l.answer
FROM source_table l
WHERE l.respondent_id = a.respondent_id AND l.question = "height") AS height
FROM source_table a
WHERE a.demographic IS NULL
GROUP BY respondent_id, a.question , a.answer;
However, your current syntax is generating a query like this:
SELECT respondents_id,
SELECT l.answer FROM source_table l where l.respondent_id = a.respondent_id
AND l.question = Age AS Age,
SELECT l.answer FROM source_table l where l.respondent_id = a.respondent_id
AND l.question = height AS height,
a.question , a.answer
FROM source_table a
WHERE a.demographic IS NULL
GROUP BY id;
There are no parentheses ()
wrapped around the SELECT ..
correlated subqueries which will return the following error
Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT l.answer FROM source_table l where l.respondent_id = a.respondent_id AND ' at line 2
You need to modify your syntax as following:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'(SELECT l.answer
FROM source_table l where l.respondent_id = a.respondent_id
AND l.question = "', b.question,'") AS ',b.question)
) INTO @sql
FROM source_table b
WHERE b.demographic IS NOT NULL;
SELECT @sql; /*added in between to check the current variable value. Removable.*/
SET @sql =
CONCAT('SELECT respondent_id, a.question , a.answer,
',@sql,'
FROM source_table a
WHERE a.demographic IS NULL
GROUP BY respondent_id, a.question , a.answer
');
SELECT @sql; /*added in between to check the current variable value. Removable.*/
PREPARE stmt FROM @sql;
EXECUTE stmt;
@FaNo_FN @ysth
I managed to fix it using the fiddle you had posted and your comments.
I added the following code between the 2 queries to check if the variable is set.
SET @sql := IF(@sql IS NULL,'',@sql);
I also added a second CONCAT()
before the GROUP_CONCAT
to add a ',' separator.
This is the link to the fiddle
我会让你的GROUP_CONCAT
有SEPARATOR ''
并开始你的第一个CONCAT(
带有','
args ,并在SELECT respondents_id
之后删除逗号。但是你的一些其他语法从视觉检查中看起来并不正确。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.