GROUP BY - 不分组NULL

sli*_*lik 62 mysql sql group-by

我试图找出一种通过使用group by函数返回结果的方法.

GROUP BY按预期工作,但我的问题是:是否可以通过忽略NULL字段组.因此它不会将NULL组合在一起,因为我仍然需要指定字段为NULL的所有行.

SELECT `table1`.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY `ancestor` 
Run Code Online (Sandbox Code Playgroud)

所以现在让我说我有5行,祖先字段是NULL,它返回我的行....但我想要所有5行.

bot*_*403 61

也许您应该在空列中添加一些内容以使它们唯一并对其进行分组?我正在寻找一些使用而不是UUID()的序列,但这可能同样有用.

SELECT `table1`.*, 
    IFNULL(ancestor,UUID()) as unq_ancestor
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY unq_ancestor
Run Code Online (Sandbox Code Playgroud)

  • 为什么不只使用主键而不是UUID()函数? (11认同)
  • 如果使用主键,则它可能与祖先值具有相同的值并导致错误 (3认同)
  • 当心; 未经测试,我不确定 UUID() 是否会为每一行生成唯一值,但只是演示了为 NULL 添加唯一值的概念。 (2认同)

Lig*_*ica 39

当通过柱分组Y,所有的行为这在值Y就是NULL被分组在一起.

这种行为是由SQL-2003标准定义的,虽然它有点令人惊讶,因为NULL它不等于NULL.

您可以通过对分组列中的数据的不同值,某些函数(在数学上说)进行分组来解决此问题.

如果您有一个独特的列,X那么这很容易.


输入

X      Y
-------------
1      a
2      a
3      b
4      b
5      c
6      (NULL)
7      (NULL)
8      d
Run Code Online (Sandbox Code Playgroud)

没有修复

SELECT GROUP_CONCAT(`X`)
  FROM `tbl`
 GROUP BY `Y`;
Run Code Online (Sandbox Code Playgroud)

结果:

GROUP_CONCAT(`foo`)
-------------------
6,7
1,2
3,4
5
8
Run Code Online (Sandbox Code Playgroud)

随着修复

SELECT GROUP_CONCAT(`X`)
  FROM `tbl`
 GROUP BY IFNULL(`Y`, `X`);
Run Code Online (Sandbox Code Playgroud)

结果:

GROUP_CONCAT(`foo`)
-------------------
6
7
1,2
3,4
5
8
Run Code Online (Sandbox Code Playgroud)

让我们仔细看看它是如何工作的

SELECT GROUP_CONCAT(`X`), IFNULL(`Y`, `X`) AS `grp`
  FROM `tbl`
 GROUP BY `grp`;
Run Code Online (Sandbox Code Playgroud)

结果:

GROUP_CONCAT(`foo`)     `grp`
-----------------------------
6                       6
7                       7
1,2                     a
3,4                     b
5                       c
8                       d
Run Code Online (Sandbox Code Playgroud)

如果您没有可以使用的唯一列,则可以尝试生成唯一的占位符值.我会将此作为练习留给读者.


Het*_*ett 21

GROUP BY IFNULL(required_field, id)

  • @T0plomj3r 如果`required_field` 和`id` 类型相同,可以使用`GROUP BY IFNULL(required_field, -id)` (3认同)
  • 简单,直截了当,这个答案应该排名第一:) (2认同)
  • 使用这个解决方案时要小心,当"id"与某些"required_field"的id相同时,你不会得到2个你想象的结果.你只能从"required_field"获得1.这是一个相当边缘的案例,但请注意它.为了确保在id-s相同的情况下你将获得2个结果,使用UUID()或CONCAT为NULL值创建唯一ID. (2认同)

ype*_*eᵀᴹ 10

SELECT table1.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS children_ids
FROM table1
WHERE (enabled = 1) 
GROUP BY ancestor
       , CASE WHEN ancestor IS NULL
                  THEN table1.id
                  ELSE 0
         END
Run Code Online (Sandbox Code Playgroud)


Ste*_*pan 6

如果你在table1中有唯一标识符,那么可能是以前解决方案的更快版本(假设它是table1.id):

SELECT `table1`.*, 
    GROUP_CONCAT(id SEPARATOR ',') AS `children_ids`,
    IF(ISNULL(ancestor),table1.id,NULL) as `do_not_group_on_null_ancestor`
FROM `table1` 
WHERE (enabled = 1) 
GROUP BY `ancestor`, `do_not_group_on_null_ancestor`
Run Code Online (Sandbox Code Playgroud)