简体   繁体   中英

What is the workaround if group_concat doesn't return a value

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;

Demo fiddle

@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_CONCATSEPARATOR ''并开始你的第一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM