如果 group_concat 不返回值,有什么解决方法

问题描述

我编写了一个查询,它根据条件将几行转换为列。

然而,也有没有行满足条件但我想返回一些结果的情况。

下面是表格示例和我要查找的结果。

源表:

id 受访者_id 人口统计 问题 回答
1 1 已检查 年龄 30
2 1 教育 大师
3 1 已检查 高度 1.8m
4 1 收入 $1
5 1 地址 国际空间站
6 1 人才 跳舞
7 2 已检查 年龄 20
8 2 教育 高中
9 2 已检查 高度 4m
10 2 收入 $3.2
11 2 地址 公海
12 2 人才 唱歌

转换后的样本结果:

id 受访者_id 年龄 高度 问题 回答
2 1 30 1.8m 教育 大师
4 1 30 1.8m 收入 $1
5 1 30 1.8m 地址 国际空间站
6 1 30 1.8m 人才 跳舞
8 2 20 4m 教育 高中
10 2 20 4m 收入 $3.2
11 2 20 4m 地址 公海
12 2 20 4m 人才 唱歌

当前 MysqL 语句:

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;

澄清一下,当有针对人口统计列“选中”的行时,上述查询有效,但是当没有“选中”单元格时,整个查询将失败。

所以我想要一个在所有条件下都有效的查询,无论是否有人口统计行。

如果没有人口统计行,查询应该返回没有新列的数据

解决方法

我对您为什么使用动态 SQL 感到有些困惑。窗口函数似乎可以满足您的需求:

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;

如果您不知道“已检查”列,我想您可以将其用作模板。

,

我认为您的目标是生成这样的查询:

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.answer;

但是,您当前的语法正在生成这样的查询:

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.answer     
        FROM   source_table a
        WHERE a.demographic IS NULL
        GROUP BY id;

没有括号 () 包裹在 SELECT .. 相关子查询周围,这将返回以下错误

错误 1064:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以获取在第 2 行的“SELECT l.answer FROM source_table l where l.respondent_id = a.respondent_id AND ”附近使用的正确语法

你需要修改你的语法如下:

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,',@sql,'
        FROM   source_table a
        WHERE a.demographic IS NULL
        GROUP BY respondent_id,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

我设法使用您发布的小提琴和您的评论修复了它。

我在 2 个查询之间添加了以下代码以检查是否设置了变量。

0

我还在 SET @sql := IF(@sql IS NULL,'',@sql); 之前添加了第二个 CONCAT() 以添加“,”分隔符。

这是指向 fiddle

的链接 ,

我会让你的 GROUP_CONCATSEPARATOR '' 并用 CONCAT( 开始你的第一个 ',' 参数,并删除 SELECT respondents_id 之后的逗号。但是您的一些其他语法仅从视觉检查中看起来并不正确。