每组选择前20行

时间:2015-07-26 16:08:02

标签: sql-server tsql select group-by greatest-n-per-group

我有一个包含3列ItemCityVisitNumber的表格。

在此表中有很多记录,我需要选择每个城市的前20个项目(根据他们的访问数量)。

例如,如果华盛顿有100个项目,纽约有250个项目,洛杉矶有500个项目,我需要为每个城市选择60个最常访问的行(华盛顿20个,纽约20个,洛杉矶20个)洛杉矶)

TSQL怎么可能?

2 个答案:

答案 0 :(得分:13)

最简单的方法是使用row_number()窗口函数根据其访问次数下降对每个城市的行进行编号,并将其用作过滤器。此查询应该适用于2005年以后的任何SQL Server版本。

select * 
from (
    select *, r = row_number() over (partition by City order by VisitNumber desc) 
    from your_table
    ) a 
where r <= 20
  and City in ('Washington', 'New York', 'Los Angeles')

这将为where子句中指定的每个城市选择前20项。

答案 1 :(得分:1)

在一个选择中:

select top 1 with ties
    Item, City, VisitNumber 
from
    your_table
where
    City in ('Washington', 'New York', 'Los Angeles')
order by 
    case 
        when row_number() over(partition by City order by VisitNumber desc) <= 20 
        then 0 
        else 1 
    end;

完整的答案可能如下:

declare @Visists table (
    Item        int, 
    City        varchar(20),
    VisitNumber int
)

insert into @Visists values
(1, 'Washington', 11),
(2, 'Washington', 22),
(3, 'Washington', 33),
(4, 'Washington', 44),
(5, 'Washington', 55),
    (6, 'New York', 66),
    (7, 'New York', 77),
    (8, 'New York', 88),
    (9, 'New York', 99),
    (10, 'New York', 5),
(11, 'Los Angeles', 12),
(12, 'Los Angeles', 23),
(13, 'Los Angeles', 34),
(14, 'Los Angeles', 45),
(15, 'Los Angeles', 56),
    (16, 'Chicago', 9),
    (17, 'Chicago', 7),
    (18, 'Chicago', 3),
    (19, 'Chicago', 2),
    (20, 'Chicago', 9);

declare @TopVisitsPerCity int = 3;
declare @TopOfCities int = 3;

with TopVisitsPerCity as
(
    select top 1 with ties
        Item, City, VisitNumber 
    from
        @Visists
    order by 
        case 
            when row_number() over(partition by City order by VisitNumber desc) <= @TopVisitsPerCity
            then 0 
            else 1 
        end
)
select top (@TopOfCities * @TopVisitsPerCity)
    *
from 
    TopVisitsPerCity
order by 
    sum(VisitNumber) over (partition by City) desc;