如何使用SQL查找每个组的最小值和最大值?
我正试图弄明白如何在SQL中实现这一点。我有一个表,在Customer表中有以下列-(Customer_Id、性别、生日)。问题是——我需要按性别找出最早和最晚出生的婴儿。基本上,最小值和最大值由不同的组确定如何使用SQL查找每个组的最小值和最大值?,sql,sql-server,Sql,Sql Server,我正试图弄明白如何在SQL中实现这一点。我有一个表,在Customer表中有以下列-(Customer_Id、性别、生日)。问题是——我需要按性别找出最早和最晚出生的婴儿。基本上,最小值和最大值由不同的组确定 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-0
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
S,然后用这种方法解决,但这样做效率很低
这是我的想法,但这也行不通。如何在一个查询中也为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
一种方法使用窗口函数:
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\u number()
这就是说,有了(性别,生日)
和(性别,生日描述)
(如果优化器有所改进,可能不再需要这两个索引),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;
实际上,一个
联合所有就足够了:)
但更好的性能是:
select gender, min(birthday), max(birthday)
from Sales..Customer group by gender
但结果将与预期略有不同。您可以使用不存在的:
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
戈登,谢谢你。排名函数只为两个性别组提供min生日(因为您只检索第一个排名)。考虑到他们的排名将永远是动态的,我如何检索最大生日数?@peppa。那是个打字错误。我将desc
放在名称中,但没有放在orderby
子句中。
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
> 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