如何使用SQL查找每个组的最小值和最大值?

时间:2019-06-16 13:37:16

标签: sql sql-server

我试图弄清楚如何用SQL做到这一点。我在客户表中有一个带有以下各列的表-(Customer_Id,性别,生日)。问题是-我需要找到Gender的最早和最新出生的人。本质上是不同组的最小值和最大值。

123 M   2017-07-05 00:00:00.000
345 M   2016-08-01 00:00:00.000
555 F   2012-01-09 00:00:00.000
567 F   2015-02-07 00:00:00.000
789 F   2013-01-02 00:00:00.000
111 F   2000-01-01 00:00:00.000
188 M   2008-09-01 00:00:00.000

结果集应如下所示

188     M       2008-09-01 00:00:00.000
123     M       2017-07-05 00:00:00.000
111     F       2000-01-01 00:00:00.000
567     F       2015-02-07 00:00:00.000

我可以做4个UNION并以这种方式找出答案,但这效率不高。

这是我想出的,但这也不起作用。如何在一个查询中同时为MAX组做到这一点?

    select a.Customer_id, a.gender, b.min_birthday
    from(
    select gender, min(birthday) min_birthday
    from Sales..Customer group by gender) b join Sales..Customer a on b.gender = a.gender 
    and b.min_birthday = a.birthday

3 个答案:

答案 0 :(得分:1)

一种方法使用窗口函数:

select customer_id, gender, birthday
from (select c.*,
             row_number() over (partition by gender order by birthday) as seqnum_asc,
             row_number() over (partition by gender order by birthday desc) as seqnum_desc
      from customer c
     ) c
where 1 in (seqnum_asc, seqnum_desc);

如果要联系,请使用rank()代替row_number()

也就是说,使用(gender, birthday)(gender, birthday desc)上的索引(如果优化程序有所改进,可能不再需要两个索引),union all方法应该表现得很好:

select c.*
from ((select top (1) c.*
       from customer c
       where gender = 'M'
       order by birthday
      ) union all
      (select top (1) c.*
       from customer c
       where gender = 'F'
       order by birthday
      ) union all
      (select top (1) c.*
       from customer c
       where gender = 'M'
       order by birthday desc
      ) union all
      (select top (1) c.*
       from customer c
       where gender = 'F'
       order by birthday desc
      )
     ) c;

答案 1 :(得分:0)

实际上一个UNION ALL就足够了:)

select gender, min(birthday) birthday, 'MIN' Aggregate
from Sales..Customer group by gender
union all
select gender, max(birthday), 'MAX'
from Sales..Customer group by gender

但是更好的痤疮应该是:

select gender, min(birthday), max(birthday)
from Sales..Customer group by gender

但是结果将与期望的略有不同。

答案 2 :(得分:0)

您可以使用“不存在”来做到这一点:

select c.* from Customer c
where not exists (
  select 1 from Customer
  where gender = c.gender and birthday < c.birthday
) or not exists (
  select 1 from Customer
  where gender = c.gender and birthday > c.birthday
)
order by c.gender, c.birthday

请参见demo
结果:

> id  | gender | birthday           
> :-- | :----- | :------------------
> 111 | F      | 01/01/2000 00:00:00
> 567 | F      | 07/02/2015 00:00:00
> 188 | M      | 01/09/2008 00:00:00
> 123 | M      | 05/07/2017 00:00:00
相关问题