GROUP BY 如果组中至少一个值满足条件,则创建组

Posted

技术标签:

【中文标题】GROUP BY 如果组中至少一个值满足条件,则创建组【英文标题】:GROUP BY Create group if at least one value in group meets condition 【发布时间】:2017-11-27 05:24:26 【问题描述】:

如果组中至少有一个值满足条件,如何创建组?

这是一个DB表test的例子:

| ID | TYPE | COLOR |
|====|======|=======|
|  1 |    1 |     R |
|  2 |    1 |     B |
|  3 |    1 |     G |
|  4 |    2 |     B |
|  5 |    2 |     G |
|  6 |    3 |     G |

我需要选择所有具有多于一行的TYPE 值,并且该类型的颜色中至少有一个是 G。

所以伪选择看起来像这样:

  select TYPE 
    from test
group by TYPE
  having count(*) > 1
     and count(COLOR = 'G') > 0

【问题讨论】:

COLOR 列中是否可以使用 NULL?同一种类型可以有重复的颜色吗?您使用什么版本的 Oracle? @mathguy ,在 COLOR 列中不能为 NULL,对于 TYPE 列中的相同值,COLOR 列中的重复值是可能的。还更正了问题“所有类型具有多于一种颜色且其中至少一种是 G”更改为“所有类型值具有多于一行,并且该类型的至少一种颜色是 G” 【参考方案1】:

随着 OP 的修改要求:

select   type
from     test
group by type
having   count(*) > 1 and count(case when color = 'G' then 0 end) > 0
;

【讨论】:

Hm... 它工作正常,但为什么该子句不是 case when color = 'G' then 1 else 0 end?在你的情况下它是如何工作的?如果color is G case语句返回0计为+1,如果color is not G case语句返回NULL,所以不计,对吧? 如果我使用 case when color = 'G' then 1 else 0 end 那么应该有另一个聚合函数 sum(case when color = 'G'然后 1 else 0 end) > 0,对吗? @IvanGerasimenko - 条件不是 case when ... - 它是 COUNT(case when ....)。不要遗漏 COUNT。 COUNT 计算所有非 NULL 值并且不关心那些非 NULL 值是什么;它不会把它们加起来,它只是计算它们。这与 SUM(case when....) 非常不同。在 COUNT(...) 方法中,我什至不需要使用数字;同样适用于count(case when color = 'G' then 'x' end)。关键是当颜色不是G 时,case 表达式的else 部分没有分配非NULL 值。 @IvanGerasimenko - 有了 COUNT,我什至可以做到count(case when color = 'G' then SYSDATE end)case 表达式现在具有 DATE 数据类型。没关系;颜色'G'的值将是非NULL,否则为NULL,这就是COUNT关心的全部。如果使用 SUM(CASE....),则无法在 CASE 表达式中分配字符或日期值,但使用 COUNT 可以。【参考方案2】:

您可以在计数(颜色)上使用内部连接

 select t1.type 
 from test  t1
 inner join (
     select type, count(color)
     from test
     where  type in (select  type from test where color='G' )
     group by type
 ) t2 on t1.type = t2.type
 group by t1.type 
 having count(*) > 1

或者用最简单的方式

   select t1.type 
   from test  t1
   inner join  test t2 on t1.type = t2.type and t2.color = 'G'
   group by t1.type 
   having count(*) > 1

【讨论】:

不需要连接,一个聚合查询就足够了。【参考方案3】:

count 只计算非null 值。将两个必需条件包装成一个的巧妙技巧是计算 case 表达式的不同数量,该表达式返回 G 的值和任何其他值的其他值:

SELECT   type
FROM     test
GROUP BY type
HAVING   COUNT(DISTINCT CASE color WHEN 'G' THEN 1 ELSE 2 END) = 2

【讨论】:

这几乎是对的。您需要在 HAVING 子句中添加一个条件以检查 count(case when color != 'G' then 1 end) > 0 以完全实现 OP 的要求。 @mathguy 哇,完全错过了,谢谢。请参阅我编辑的答案,了解将两个条件合并为一个的巧妙技巧。 :-) 我也是这么写的。或者(为了避免 DISTINCT) - max(case...) != min(case...)

以上是关于GROUP BY 如果组中至少一个值满足条件,则创建组的主要内容,如果未能解决你的问题,请参考以下文章

having和group by的区别?

SQL中只要用到聚合函数就一定要用到group by 吗?

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?

如果每个值至少满足一个条件,则将某个值分配给所有其他值

【MySQL】分组查询(GROUP BY)

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?