如何在T / SQL中按一列分组并检索具有另一列最小值的行?

问题描述

这是我模拟你的table:

declare @Borg table (
    ID int,
    Foo int,
    Bar int,
    Blagh int
)
insert into @Borg values (1,10,20,30)
insert into @Borg values (2,10,5,1)
insert into @Borg values (3,20,50,70)
insert into @Borg values (4,20,75,12)

然后,您可以进行匿名内部联接以获取所需的数据。

select B.* from @Borg B inner join 
(
    select Foo,
        MIN(Bar) MinBar 
    from @Borg 
    group by Foo
) FO
on FO.Foo = B.Foo and FO.MinBar = B.Bar

亚当·罗宾逊(Adam Robinson)有益地指出:“当Bar的最小值重复时,此解决方案有可能返回多行,并消除bar为的foo的任何值null

根据您的用例,重复Bar的重复值可能是有效的-如果您想在Borg中找到Bar最小的所有值,那么同时获得两个结果似乎是可行的方法

如果您需要捕获NULLs要聚合的字段(在这种情况下为MIN),则可以coalesce使用具有可接受的高(或低)值的NULL(这是hack):

...
MIN(coalesce(Bar,1000000)) MinBar -- A suitably high value if you want to exclude this row, make it suitably low to include
...

或者,您可以使用UNION,并将所有这些值附加到结果集的底部

on FO.Foo = B.Foo and FO.MinBar = B.Bar
union select * from @Borg where Bar is NULL

后者不会将@Borg中的值分组为相同的Foo值,因为它不知道如何在它们之间进行选择。

解决方法

因此,我知道这是一个非常愚蠢的问题,但是(正如冗长的标题所言),我想知道以下操作:

我有一个这样的表:

ID Foo Bar Blagh
----------------
1  10  20  30
2  10  5   1
3  20  50  40
4  20  75  12

我想按Foo分组,然后拉出具有最小Bar的行,即我想要以下内容:

ID Foo Bar Blagh
----------------
2  10  5   1
3  20  50  40

我无法终生制定出正确的SQL来检索此信息。我想要类似的东西:

SELECT ID,Foo,Bar,Blagh
FROM Table
GROUP BY Foo
HAVING(MIN(Bar))

但是,这显然是行不通的,因为这完全是无效的HAVING语法,并且ID,Foo,Bar和Blagh不会汇总。

我究竟做错了什么?