2016-08-02 1 views
1

Comment puis-je retourner uniquement les 3 premières valeurs par paire nom-date dans ce qui suit?Sql Sélectionnez le top 3 par groupe de cumul

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 

Ce rendement version actuelle:

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 

Je voudrais revenir:

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 

Je pensais qu'il y aurait un moyen simple mais ne peut pas comprendre!

Répondre

1
;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 

Retours

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 
+0

Cela fonctionne parfaitement et est le seul jusqu'à présent qui a fonctionné pour moi sans modifications. – conor

1

utilisant peut-être row_number avec un subquery peut atteindre vos résultats:

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 

Vous pourriez être en mesure d'utiliser à la place row_number() over (partition by name order by sum(val)) et supprimer l'un des sous-requêtes.

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 
0

Vous devez utiliser RANK() ou ROW_NUMBER() pour indexer la sortie, alors vous aurez besoin d'envelopper cela dans une sous requête et filtrer toutes les lignes au-dessus quel que soit le numéro que vous avez besoin.

Comme ceci:

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 
+0

Vous ne voudriez pas partitionner par date, que:

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; 

cette volonté Si cela ne fonctionne pas (je ne peux pas tester en ce moment), donnera à chaque ligne un numéro de ligne 1. – mrtig

0

C'est un grand complexe en raison de la rollup. Je pense que ce qui suit fonctionnera:

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;