首页 > 解决方案 > MySQL 按空值和非空值分组

问题描述

我有一张这样的桌子:

id | cluster_id | user_id | name      | ...
1  | 1          | 1       | test name
2  | 1          | 3       | other
3  | null       | 1       | one more
4  | 2          | 1       | foo
5  | null       | 1       | bar
6  | 1          | 1       | baz

我想创建一个按cluster_id列分组的查询,但只按具有非空值的列分组,这样我就得到了这样的结果:

id | cluster_id | user_id | ...
1  | 1          | 1       | test name
3  | null       | 1       | one more
4  | 2          | 1       | foo
5  | null       | 1       | bar

我想要一个具有不同 cluster_ids 的列表,但仅限于 cluster_id 不为空的地方。我也想过滤任意列,如user_id.

在上面的结果中,我还查询了user_id,其中user_id是 1。

如何创建这样的查询?

提前致谢!

标签: mysqlgroup-bydistinct

解决方案


查询很简单。

GROUP BY 也适用于 NULL 值

我做了两个查询,第一个包含 user_id 最后一个不包含

您必须以 id 作为主键进行测试,并查看排除 NULL 是否会带来一些性能

CREATE TABLE tab1 (
  `id` INTEGER,
  `cluster_id` int,
  `user_id` INTEGER,
  `name` VARCHAR(20)
);
INSERT INTO tab1
  (`id`, `cluster_id`, `user_id`, `name`)
VALUES
  ('1', '1', '1', 'test name'),
  ('2', '1', '3', 'other'),
  ('3', null, '1', 'one more'),
  ('4', '2', '1', 'foo'),
  ('5', null, '1', 'bar'),
  ('6', '1', '1', 'baz');
SELECT * FROM  tab1 WHERE `id` IN (SELECT MIN(`id`) FROM tab1 GROUP BY `cluster_id`,`user_id`)
UNION 
SELECT * FROM tab1 WHERE `cluster_id` IS NULL
编号 | cluster_id | 用户 ID | 姓名     
-: | ---------: | ------: | :--------
 1 | 1 | 1 | 测试名称
 2 | 1 | 3 | 其他    
 3 |       | 1 | 多一个
 4 | 2 | 1 | 富      
 5 |       | 1 | 酒吧      
SELECT * FROM  tab1 WHERE `id` IN (SELECT MIN(`id`) FROM tab1 WHERE `cluster_id` IS NOT NULL GROUP BY `cluster_id`,`user_id`)
UNION 
SELECT * FROM tab1 WHERE `cluster_id` IS NULL
编号 | cluster_id | 用户 ID | 姓名     
-: | ---------: | ------: | :--------
 1 | 1 | 1 | 测试名称
 2 | 1 | 3 | 其他    
 4 | 2 | 1 | 富      
 3 |       | 1 | 多一个
 5 |       | 1 | 酒吧      
SELECT * FROM  tab1 WHERE `id` IN (SELECT MIN(`id`) FROM tab1 GROUP BY `cluster_id`)
UNION 
SELECT * FROM tab1 WHERE `cluster_id` IS NULL
编号 | cluster_id | 用户 ID | 姓名     
-: | ---------: | ------: | :--------
 1 | 1 | 1 | 测试名称
 3 |       | 1 | 多一个
 4 | 2 | 1 | 富      
 5 |       | 1 | 酒吧      
SELECT * FROM  tab1 WHERE `id` IN (SELECT MIN(`id`) FROM tab1 WHERE `cluster_id` IS NOT NULL GROUP BY `cluster_id`)
UNION 
SELECT * FROM tab1 WHERE `cluster_id` IS NULL
编号 | cluster_id | 用户 ID | 姓名     
-: | ---------: | ------: | :--------
 1 | 1 | 1 | 测试名称
 4 | 2 | 1 | 富      
 3 |       | 1 | 多一个
 5 |       | 1 | 酒吧      

db<>在这里摆弄


推荐阅读