【问题标题】:Sql Select top 3 per rollup groupSql 选择每个汇总组的前 3 个
【发布时间】:2016-12-08 12:01:35
【问题描述】:

如何仅返回以下每个 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

当前版本返回:

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

我想退货:

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

我以为会有一个简单的方法,但我想不通!

【问题讨论】:

    标签: sql sql-server group-by rollup ssms-2014


    【解决方案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
    

    返回

    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
    

    【讨论】:

    • 这是完美的工作,是迄今为止唯一一个对我有用的没有编辑的。
    【解决方案2】:

    也许使用row_numbersubquery 可以达到你的效果:

    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
    

    【讨论】:

      【解决方案3】:

      您需要使用 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
      

      【讨论】:

      • 你不想按日期分区,这会给每一行一个行号 1。
      【解决方案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;
      

      【讨论】:

        猜你喜欢
        • 2020-07-12
        • 1970-01-01
        • 2014-06-24
        • 2012-07-03
        • 2014-04-06
        • 1970-01-01
        • 2023-03-16
        • 2015-04-03
        • 1970-01-01
        相关资源
        最近更新 更多