Sql Select 每个汇总组的前 3 名
Sql Select top 3 per rollup group
我如何 return 仅 return 以下每个 Name-datee 对的前 3 个值?
DECLARE @t TABLE(NAME NVARCHAR(MAX),datee date,val money)
insert INTO @t SELECT 'a','2012-01-02',100
insert INTO @t SELECT 'a','2012-01-02',100
insert INTO @t SELECT 'a','2012-01-03',100
insert INTO @t SELECT 'a','2012-01-05',150
insert INTO @t SELECT 'a','2012-01-06',200
insert INTO @t SELECT 'b','2012-01-07',200
insert INTO @t SELECT 'b','2012-01-07',400
insert INTO @t SELECT 'b','2012-01-09',500
insert INTO @t SELECT 'b','2012-01-12',600
insert INTO @t SELECT 'b','2012-01-13',100
SELECT Name, datee, SUM(val) sumval from @t
GROUP BY rollup(NAME ,datee)
order by Name, sumval desc
当前版本 returns:
Name datee sumval
NULL NULL 2450.00
a NULL 650.00
a 2012-01-02 200.00
a 2012-01-06 200.00
a 2012-01-05 150.00
a 2012-01-03 100.00
b NULL 1800.00
b 2012-01-07 600.00
b 2012-01-12 600.00
b 2012-01-09 500.00
b 2012-01-13 100.00
我愿意return:
Name datee sumval
NULL NULL 2450.00
a NULL 650.00
a 2012-01-02 200.00
a 2012-01-06 200.00
a 2012-01-05 150.00
b NULL 1800.00
b 2012-01-07 600.00
b 2012-01-12 600.00
b 2012-01-09 500.00
我以为会有一个简单的方法,但想不通!
也许使用 row_number
和 subquery
可以达到你的结果:
select *
from (
select *,
row_number() over (partition by name order by sumval desc) rn
from (
select Name, datee, SUM(val) sumval
from @t
group by rollup(NAME ,datee)
order by Name, sumval desc
) t
) t
where rn <= 3 or datee is null
您可以改用 row_number() over (partition by name order by sum(val))
并删除其中一个子查询。
select *
from (
select Name, datee, SUM(val) sumval,
row_number() over (partition by name order by SUM(val) desc) rn
from @t
group by rollup(NAME ,datee)
order by Name, sumval desc
) t
where rn <= 3 or datee is null
您需要使用 RANK()
或 ROW_NUMBER()
来索引输出,然后您需要将其包装到一个子查询中,并过滤掉任何超过您需要的数字的行。
像这样:
SELECT
t.Name,
t.date,
t.sumval
FROM
(
SELECT
Name,
date,
SUM(val) sumval,
ROW_NUMBER() OVER (ORDER BY sumval, PARTITION BY name) RowId
from @t GROUP BY rollup(NAME ,datee)
) t
WHERE RowId <= 3
order by Name, sumval desc
;with cteBase as (
Select Name
,datee
,sumval=SUM(val)
,rowNr=ROW_NUMBER() over (Partition By Name Order by sum(Val) Desc)
From @t
GROUP BY rollup(NAME ,datee)
)
Select *
From cteBase
Where RowNr<=4
order by Name, sumval desc
Returns
Name datee sumval rowNr
NULL NULL 2450.00 1
a NULL 650.00 1
a 2012-01-02 200.00 2
a 2012-01-06 200.00 3
a 2012-01-05 150.00 4
b NULL 1800.00 1
b 2012-01-07 600.00 2
b 2012-01-12 600.00 3
b 2012-01-09 500.00 4
由于rollup
,这是一个很大的复杂性。我认为以下方法可行:
SELECT t.*
FROM (SELECT Name, datee, SUM(val) as sumval,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY SUM(val) DESC) as seqnum
FROM @t t
GROUP BY rollup(NAME, datee)
) t
WHERE seqnum <= 3 or Datee is NULL
ORDER BY Name, sumval desc;
如果这不起作用(我现在无法测试),这将:
SELECT Name, datee, sumval
FROM (SELECT Name, datee, SUM(sumval) as sumval, MAX(seqnum) as seqnum
FROM (SELECT Name, datee, SUM(val) as sumval,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY SUM(val) DESC) as seqnum
FROM @t t
GROUP BY Name, datee
) t
GROUP BY rollup(NAME, datee)
) t
WHERE seqnum <= 3 or Date is NULL
ORDER BY Name, sumval desc;
我如何 return 仅 return 以下每个 Name-datee 对的前 3 个值?
DECLARE @t TABLE(NAME NVARCHAR(MAX),datee date,val money)
insert INTO @t SELECT 'a','2012-01-02',100
insert INTO @t SELECT 'a','2012-01-02',100
insert INTO @t SELECT 'a','2012-01-03',100
insert INTO @t SELECT 'a','2012-01-05',150
insert INTO @t SELECT 'a','2012-01-06',200
insert INTO @t SELECT 'b','2012-01-07',200
insert INTO @t SELECT 'b','2012-01-07',400
insert INTO @t SELECT 'b','2012-01-09',500
insert INTO @t SELECT 'b','2012-01-12',600
insert INTO @t SELECT 'b','2012-01-13',100
SELECT Name, datee, SUM(val) sumval from @t
GROUP BY rollup(NAME ,datee)
order by Name, sumval desc
当前版本 returns:
Name datee sumval
NULL NULL 2450.00
a NULL 650.00
a 2012-01-02 200.00
a 2012-01-06 200.00
a 2012-01-05 150.00
a 2012-01-03 100.00
b NULL 1800.00
b 2012-01-07 600.00
b 2012-01-12 600.00
b 2012-01-09 500.00
b 2012-01-13 100.00
我愿意return:
Name datee sumval
NULL NULL 2450.00
a NULL 650.00
a 2012-01-02 200.00
a 2012-01-06 200.00
a 2012-01-05 150.00
b NULL 1800.00
b 2012-01-07 600.00
b 2012-01-12 600.00
b 2012-01-09 500.00
我以为会有一个简单的方法,但想不通!
也许使用 row_number
和 subquery
可以达到你的结果:
select *
from (
select *,
row_number() over (partition by name order by sumval desc) rn
from (
select Name, datee, SUM(val) sumval
from @t
group by rollup(NAME ,datee)
order by Name, sumval desc
) t
) t
where rn <= 3 or datee is null
您可以改用 row_number() over (partition by name order by sum(val))
并删除其中一个子查询。
select *
from (
select Name, datee, SUM(val) sumval,
row_number() over (partition by name order by SUM(val) desc) rn
from @t
group by rollup(NAME ,datee)
order by Name, sumval desc
) t
where rn <= 3 or datee is null
您需要使用 RANK()
或 ROW_NUMBER()
来索引输出,然后您需要将其包装到一个子查询中,并过滤掉任何超过您需要的数字的行。
像这样:
SELECT
t.Name,
t.date,
t.sumval
FROM
(
SELECT
Name,
date,
SUM(val) sumval,
ROW_NUMBER() OVER (ORDER BY sumval, PARTITION BY name) RowId
from @t GROUP BY rollup(NAME ,datee)
) t
WHERE RowId <= 3
order by Name, sumval desc
;with cteBase as (
Select Name
,datee
,sumval=SUM(val)
,rowNr=ROW_NUMBER() over (Partition By Name Order by sum(Val) Desc)
From @t
GROUP BY rollup(NAME ,datee)
)
Select *
From cteBase
Where RowNr<=4
order by Name, sumval desc
Returns
Name datee sumval rowNr
NULL NULL 2450.00 1
a NULL 650.00 1
a 2012-01-02 200.00 2
a 2012-01-06 200.00 3
a 2012-01-05 150.00 4
b NULL 1800.00 1
b 2012-01-07 600.00 2
b 2012-01-12 600.00 3
b 2012-01-09 500.00 4
由于rollup
,这是一个很大的复杂性。我认为以下方法可行:
SELECT t.*
FROM (SELECT Name, datee, SUM(val) as sumval,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY SUM(val) DESC) as seqnum
FROM @t t
GROUP BY rollup(NAME, datee)
) t
WHERE seqnum <= 3 or Datee is NULL
ORDER BY Name, sumval desc;
如果这不起作用(我现在无法测试),这将:
SELECT Name, datee, sumval
FROM (SELECT Name, datee, SUM(sumval) as sumval, MAX(seqnum) as seqnum
FROM (SELECT Name, datee, SUM(val) as sumval,
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY SUM(val) DESC) as seqnum
FROM @t t
GROUP BY Name, datee
) t
GROUP BY rollup(NAME, datee)
) t
WHERE seqnum <= 3 or Date is NULL
ORDER BY Name, sumval desc;