SELECT 每组前 20 行
SELECT TOP 20 rows for each group
我有一个 table,其中包含 3 列 Item
、City
和 VisitNumber
。
这个table里面有很多条记录,我需要select每个城市的前20条(根据访问次数)
例如,如果华盛顿有 100 个项目,纽约有 250 个项目,洛杉矶有 500 个项目,我需要 select 每个城市的 60 个访问量最大的行(华盛顿 20 个,华盛顿 20 个纽约,洛杉矶 20)
TSQL
怎么可能?
最简单的方法是使用 row_number()
window 函数根据访问次数降序对每个城市的行进行编号,并将其用作过滤器。此查询应适用于 2005 年以后的任何 SQL 服务器版本。
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')
这将 select where 子句中指定的每个城市的前 20 个项目。
一个select:
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;
我有一个 table,其中包含 3 列 Item
、City
和 VisitNumber
。
这个table里面有很多条记录,我需要select每个城市的前20条(根据访问次数)
例如,如果华盛顿有 100 个项目,纽约有 250 个项目,洛杉矶有 500 个项目,我需要 select 每个城市的 60 个访问量最大的行(华盛顿 20 个,华盛顿 20 个纽约,洛杉矶 20)
TSQL
怎么可能?
最简单的方法是使用 row_number()
window 函数根据访问次数降序对每个城市的行进行编号,并将其用作过滤器。此查询应适用于 2005 年以后的任何 SQL 服务器版本。
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')
这将 select where 子句中指定的每个城市的前 20 个项目。
一个select:
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;