【问题标题】:GROUP BY - do not group NULLGROUP BY - 不分组 NULL
【发布时间】:2011-06-03 02:26:16
【问题描述】:

我正在尝试找出一种使用 group by 函数返回结果的方法。

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

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

所以现在假设我有 5 行并且祖先字段为 NULL,它返回我 1 行....但我想要全部 5。

【问题讨论】:

  • 您可以使用GROUP BY COALESCE(GroupingColumn, PrimaryKey),可能需要对数据类型、复合 PK 等进行一些调整。
  • @Tomalak Geret'kal:Joe Celko 引用:“在 SQL 中,当你执行 GROUP BY 时,你会得到一个分区,并且 NULL 都被放入一个组中。这在ANSI X3H2 委员会。如果我们使用严格相等,每个 NULL 将是它自己的类,事情会一团糟。所以我们发明了分组。分组对于许多查询很方便,而不仅仅是聚合函数。它具有很好的属性我们回到二值逻辑 (2VL),我们喜欢这样。”
  • 建议:删除行WHERE ancestor is NOT NULL,然后删除UNIONWHERE ancestor is NULL,使用children_ids 的适当默认值。我认为这样的查询会更容易维护。
  • @onedaywhen:这是个好主意。

标签: mysql sql group-by


【解决方案1】:

将多个表和group_concat 不同的列和列的总和合并为(唯一主键或外键)列以在同一行显示一个值

select column1,column2,column3,GROUP_CONCAT(if(column4='', null, column4)) as 
column4,sum(column5) as column5
from (
      select column1,group_concat(column2) as column2,sum(column3 ) as column3,'' as 
      column4,'' as column5
      from table1 
      group by column1

      union all

      select column1,'' as column2,'' as column3,group_concat(column4) as 
      column4,sum(column5) as column5
      from table 2 
      group by column1
     ) as t
     group by column1

【讨论】:

    【解决方案2】:

    GROUP BY IFNULL(required_field, id)

    【讨论】:

    • 简单,直截了当,这个答案应该排名靠前:)
    • 在使用此解决方案时要小心,当“id”与某些“required_field”的 id 相同时,您不会得到预期的 2 个结果。您只会从“required_field”中获得 1 个。这是一个非常极端的案例,但请注意这一点。为确保在 id-s 相同的情况下得到 2 个结果,请使用 UUID() 或 CONCAT 为 NULL 值创建唯一 ID。
    • @T0plomj3r 如果required_fieldid属于同一类型,可以使用GROUP BY IFNULL(required_field, -id)
    【解决方案3】:

    Y 列分组时,Y 中的值为NULL 的所有行都被分组在一起。

    This behaviour is defined by the SQL-2003 standard,虽然这有点令人惊讶,因为NULL 不等于NULL

    您可以通过对不同的值进行分组来解决此问题,即分组列中数据的一些函数(从数学上讲)。

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


    输入

    X      Y
    -------------
    1      a
    2      a
    3      b
    4      b
    5      c
    6      (NULL)
    7      (NULL)
    8      d
    

    没有修复

    SELECT GROUP_CONCAT(`X`)
      FROM `tbl`
     GROUP BY `Y`;
    

    结果:

    GROUP_CONCAT(`foo`)
    -------------------
    6,7
    1,2
    3,4
    5
    8
    

    有修复

    SELECT GROUP_CONCAT(`X`)
      FROM `tbl`
     GROUP BY IFNULL(`Y`, `X`);
    

    结果:

    GROUP_CONCAT(`foo`)
    -------------------
    6
    7
    1,2
    3,4
    5
    8
    

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

    SELECT GROUP_CONCAT(`X`), IFNULL(`Y`, `X`) AS `grp`
      FROM `tbl`
     GROUP BY `grp`;
    

    结果:

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

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

    【讨论】:

      【解决方案4】:
      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
      

      【讨论】:

      • 我喜欢这个回复的简洁性
      • GROUP BY IFNULL(Y, X); => 这是游戏规则改变者:)
      【解决方案5】:

      如果您在 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`
      

      【讨论】:

        【解决方案6】:

        也许您应该在空列中添加一些内容以使它们唯一并对其进行分组?我一直在寻找某种序列来代替 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
        

        【讨论】:

        • 感谢您的成功!感谢您向我介绍 UUID 功能。
        • 小心;未经测试,我不确定 UUID() 是否会为每一行生成唯一值,但只是演示了为 NULLS 添加唯一值的概念。
        • 为什么不直接使用主键而不是 UUID() 函数?
        • uuid 没有为每一行提供唯一的 id,必须使用 pk 代替
        • 如果使用主键,可能与祖先值相同,导致错误
        猜你喜欢
        • 1970-01-01
        • 2018-04-30
        • 2015-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-01
        相关资源
        最近更新 更多