Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用SQL查找每个组的最小值和最大值?_Sql_Sql Server - Fatal编程技术网

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

如何使用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

我正试图弄明白如何在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-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