内置的分析功能不应用于前N行

时间:2019-02-27 16:36:03

标签: sql sql-server

想知道是否存在对分析功能的内置支持,这些支持不应用于我的SQL查询的前 n 行。

示例代码:

;with cte (num, dollar) as
(
    select 1, cast(1.45 as decimal(12,2))
    union all
    select num + 1, cast(dollar + 1.00 as decimal(12,2))
    from cte
    where num < 20
)
select cte.num, cte.dollar
    , avg(cte.dollar) over (order by cte.num ROWS 3 PRECEDING) as ThreeMonthAvg
    , avg(cte.dollar) over (order by cte.num ROWS 6 PRECEDING) as SixMonthAvg
from cte

在这里,我分别获得了三个月和六个月美元的滚动平均值。显然,这将为每一行填充依赖于分析平均数的那些列的值。但是,由于不是真正的第1行和第2行的前三行的平均值,因此无论什么工作,我都希望显示0,null。

我当前的解决方案:在我的实际设置中使用row_number()来使用rownum,或者在此为测试用例使用递归构造的行num。无论如何,而不是个案说明。

--solution
;with cte (num, dollar) as
(
    select 1, cast(1.45 as decimal(12,2))
    union all
    select num + 1, cast(dollar + 1.00 as decimal(12,2))
    from cte
    where num < 20
)
select cte.num, cte.dollar
    , case when cte.num >= 3 then avg(cte.dollar) over (order by cte.num ROWS 3 PRECEDING) else 0 end as ThreeMonthAvg
    , case when cte.num >= 6 then avg(cte.dollar) over (order by cte.num ROWS 6 PRECEDING) else 0 end as SixMonthAvg
from cte

是否存在一种内置的方法来告诉该函数“跳过”该函数以将其应用于前n个行,而不是将该行从结果集中过滤掉?

检查了Microsoft文档,但我自己找不到支持或否认的任何内容。

1 个答案:

答案 0 :(得分:1)

没有内置方法,但是此版本可在更多情况下使用:

with cte (num, dollar) as (
      select 1, cast(1.45 as decimal(12,2))
      union all
      select num + 1, cast(dollar + 1.00 as decimal(12,2))
      from cte
      where num < 20
     )
select cte.num, cte.dollar,
       (case when count(*) over (order by cte.num ROWS 3 PRECEDING) = 3
             then avg(cte.dollar) over (order by cte.num ROWS 3 PRECEDING)
        end) as ThreeMonthAvg,
       (case when count(*) over (order by cte.num ROWS 6 PRECEDING) = 6
             then avg(cte.dollar) over (order by cte.num ROWS 6 PRECEDING)
        end) as SixMonthAvg
from cte;

这实际上是计算进入平均值的行,而不是取决于特定的数值。