【问题标题】:MySQL GROUP_CONCAT vs. COALESCE concerning NULL valuesMySQL GROUP_CONCAT vs. COALESCE 关于 NULL 值
【发布时间】:2012-09-30 21:33:03
【问题描述】:

更新

我刚刚注意到,在服务器中,table3.note 列的值是 NULL,而在我的本地计算机上它们是空字符串。在这个令人尴尬的发现之后,我进行了一些测试,并且在两个平台上一切正常。

如果我有两个单元格并且第二个单元格包含实际值(第一个是NULL),这就是它们产生的结果:

//1st
GROUP_CONCAT(COALESCE(`table3`.`note`, '') SEPARATOR ';') AS `table3_note`
//var_dump(): array(2) { [0]=> string(0) "" [1]=> string(4) "Test" } 

//2nd
GROUP_CONCAT(`table3`.`note`) SEPARATOR ';') AS `table3_note`
//var_dump(): array(1) { [0]=> string(4) "Test" }

所以第一个查询 (COALESCE) 将 NULLs 检索为空字符串,第二个查询从结果集中删除所有 NULL 值。 (这是不可接受的,因为我有很多数组,它们需要同步。)

由于我的错误,原来的问题解决了。我仍然想知道为什么GROUP_CONCAT 会忽略NULLs,即使选中。

这是正常工作的查询(不删除NULLs):

SELECT `table1`.*
  GROUP_CONCAT(COALESCE(`table3`.`id`, '') SEPARATOR ';') AS `t3_id`,
  GROUP_CONCAT(COALESCE(`table3`.`note`, '') SEPARATOR ';') AS `t3_note`,
  FROM `table1`
    LEFT JOIN `table3` ON `table3`.`id` = `table1`.`id`
      GROUP BY `table1`.`id`

那么为什么这个忽略NULLs? (忽略NULL 值的更多查询选项位于原始问题部分。)

SELECT `table1`.*
  GROUP_CONCAT(`table3`.`id` SEPARATOR ';') AS `t3_id`,
  GROUP_CONCAT(`table3`.`note` SEPARATOR ';') AS `t3_note`,
  FROM `table1`
    LEFT JOIN `table3` ON `table3`.`id` = `table1`.`id`
      GROUP BY `table1`.`id`

原始问题(不重要,我的错……)

我的查询的一部分使用三个表(1:n 关系,我将多行从 table2table3 映射到单个 table1 行)。获取单个单元格值的两种方法:

 //1st
 GROUP_CONCAT(COALESCE(`table3`.`note`, '') SEPARATOR ';') AS `table3_note`

 //2nd
 GROUP_CONCAT(`table3`.`note`) SEPARATOR ';') AS `table3_note`

两者都可以在本地机器上正常工作,但只有第一个在服务器上。在我的本地机器上,当使用第一个或第二个选项(使用var_dump())时,我得到了正确数量的空数组值。在服务器上,如果任何 table3_note 上没有值(有许多 table3_ids 和查询中未显示的其他字段),则第二个选项仅返回一个空数组。

那么问题是为什么?如果手册中没有非空值,这两个函数都声称返回NULL

以下信息是否相关或我在手册中遗漏了什么?

  • 本地机器:MySQL Client API 版本 5.1.44
  • 服务器:MySQL 客户端 API 版本 5.0.51a

答案是否如此简单,以至于服务器像我的本地机器一样处理COALESCE 函数,但是由于不匹配的 MySQL Client API 版本,GROUP_CONCAT 函数的处理方式不同?

我现在有一个可行的解决方案,所以从某种意义上说,这不是一个真正的问题,我需要解决这个问题。我只是想知道为什么会这样。像我一样使用COALESCE 有什么陷阱吗?使用for 循环打印数组时是否存在未正确同步的危险? (至少快速测试没有发现任何问题。)


最后的笔记。我尝试使用这些方法和其他一些方法(IFNULLIS NULL 等),例如在这些问题中建议的方法:

但结果是一样的:在本地机器上工作,但在服务器上不行。以下查询:

//another option for the query
IF(SUM(`table3`.`note` IS NULL) = 0, GROUP_CONCAT(`table3`.`note` SEPARATOR ';'), NULL) AS `table3_note`

//and another one...
ISNULL(GROUP_CONCAT(`table3`.`note` SEPARATOR ';'), '') AS `table3_note`

MySQL manual also says:

除非另有说明,否则组函数会忽略 NULL 值。

这是否意味着 COALESCE 不会像 GROUP_CONCAT 那样忽略 NULL 值,即使已选中?这仍然不能解释服务器和本地机器的不同行为。还是这样?

【问题讨论】:

  • 除非您显示查询的 GROUP BY 部分,否则无法弄清楚为什么像 GROUP_CONCAT 这样的摘要函数可能无法按您希望的方式工作。如果您的查询中没有GROUP BY,请将其放在那里。或者,理解这个网页的每一个字。 dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html 说真的。
  • 请将您的解决方案移至答案并编辑您的问题。
  • 在设计 SQL 和/或 mySQL 开始开发的时代,我想跳过 NULL 更有意义。如果使用 SQL 直接输出人类可读的报告,那就更有意义了。但如今,它主要用于向复杂程序和 OO 代码提供数据,这需要更好的可预测性和精度。

标签: mysql null


【解决方案1】:

这是正常工作的查询(不删除NULLs):

SELECT `table1`.*
  GROUP_CONCAT(COALESCE(`table3`.`id`, '') SEPARATOR ';') AS `t3_id`,
  GROUP_CONCAT(COALESCE(`table3`.`note`, '') SEPARATOR ';') AS `t3_note`,
  FROM `table1`
    LEFT JOIN `table3` ON `table3`.`id` = `table1`.`id`
      GROUP BY `table1`.`id`

原始问题保持不变。它非常混乱且难以理解,但上面的查询对我有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-29
    • 2011-06-12
    • 1970-01-01
    • 2013-07-14
    • 2011-06-27
    • 2012-07-14
    • 2016-10-16
    • 1970-01-01
    相关资源
    最近更新 更多