C# sqlserver:条件聚合;

C# sqlserver:条件聚合;,c#,sql,sql-server,sql-server-2012,C#,Sql,Sql Server,Sql Server 2012,我有一张这样的桌子: Year Value ----------------- 2013 -0.0016 2014 -0.0001 2015 0.0025 2016 -0.0003 2017 0.0023 2018 0.0002 Year Value AggCol 2013 -0.0016 -0.0016 2014 -

我有一张这样的桌子:

  Year       Value
  -----------------
  2013      -0.0016
  2014      -0.0001
  2015       0.0025
  2016      -0.0003
  2017       0.0023
  2018       0.0002
  Year       Value        AggCol
  2013      -0.0016      -0.0016
  2014      -0.0001      -0.0017
  2015       0.0025       0.0008
  2016      -0.0003      -0.0003
  2017       0.0023       0.002
  2018       0.0002       0.0002
我需要执行一个条件聚合,生成一个新列。条件如下:

如果该值为负值,则聚合将开始,直到该值为正值才停止。然后什么都没有,直到值再次为负。。。结果如下所示:

  Year       Value
  -----------------
  2013      -0.0016
  2014      -0.0001
  2015       0.0025
  2016      -0.0003
  2017       0.0023
  2018       0.0002
  Year       Value        AggCol
  2013      -0.0016      -0.0016
  2014      -0.0001      -0.0017
  2015       0.0025       0.0008
  2016      -0.0003      -0.0003
  2017       0.0023       0.002
  2018       0.0002       0.0002
这个udf与我得到的最接近:

create function dbo.fn(@cYear numeric, @rate float)
returns float
as 
begin
    declare @pYear numeric
    declare @return float

    set @pYear = @cYear - 1

    set @return = (select 
                        case 
                            when Value < 0 and @rate > 0  then null 
                            when Value < 0 then Value + @rate
                            else @rate 
                        end 
                   from Table1 
                   where [year] = @pYear)

    return @return
end
我可以用c语言回答这个问题,但我更喜欢SQL。我所做的函数的问题是,当值为正值时,我需要能够从上一行获取结果以添加到值中

我整晚都在这里寻找线索,但毫无乐趣

编辑:因此,请将这些作为一年的CPI值,由您的运营商应用到您的手机账单上。。。他们只会按CPI增加你的账单,如果CPI为负,他们永远不会减少。。。但如果当年CPI为正值或总和为正值,它们将用当年CPI抵消前几年的负CPI

这可能有帮助,也可能没有帮助,但情况就是这样,哈哈

DECLARE @t TABLE ( [Year] INT, Value MONEY )

INSERT  INTO @t
VALUES  ( 2013, -0.0016 ),
        ( 2014, -0.0001 ),
        ( 2015, 0.0025 ),
        ( 2016, -0.0003 ),
        ( 2017, 0.0023 ),
        ( 2018, 0.0002 )

SELECT  t1.Year ,
        t1.Value ,
        oa.AggCol
FROM    @t t1
        OUTER APPLY ( SELECT    SUM(Value) AS AggCol
                      FROM      @t t2
                      WHERE     Year <= t1.Year
                                AND Year > ( SELECT ISNULL(MAX(Year), 0)
                                             FROM   @t
                                             WHERE  Year < t1.Year AND Value > 0)
                    ) oa

这意味着:对于每一行,给我一个小于或等于当前行和大于最大行的值之和,该值在当前行之前显示为正值,如果没有找到,则从0开始。您也可以使用窗口函数执行此操作:

;值为 选择年份、值、, 按年份排列的订单价值滞后于上一个价值 来自表1 ,旗为 选择年份、值、, 案例 当值<0且prevValue>0时,则2-下一个切片 当值<0或prevValue<0时,则1-相同的切片 当值>0且prevValue>0时,则-1-不在切片中 以旗帜结束 从以前的价值观 ,离岛为 选择年份、值、, 案例 当flag=-1时,则为-1 否则,每年都会超过订单 - 按年份列出的订单行数 以玻璃钢结尾 来自旗帜 选择年份、值、, 案例 当grp=-1时,则为 按grp顺序按年份划分的分区上的值 以AggCol结束 来自岛屿 按年订购 其思想是识别应用运行和的行孤岛

注意,这是一个不同于您提供的数据集!以下是结果

原始测试数据的问题在于,它没有考虑需要多个连续的正记录才能使运行和为正的情况。随后,在我发布我的答案时,其他两个答案都是错误的。因此,我仅将2014年的记录更改为正值.0001,您可以看到此解决方案是如何工作的,而其他解决方案则没有

对于窗口函数,可能有一些方法可以做到这一点,但递归cte非常简单,因此我采用了这种方法:

首先在数据集上构建一个行号,以便在联接中使用,以说明数据集中缺少年份或其他情况。 接下来,使用行号一次构建递归cte和步骤1行,并根据前面的行值是正值还是负值来确定是否需要重置或添加聚合值。 以下是Giorgos&Giorgi回答的结果,如果您更改了测试数据:

Year    Value        AggCol
2013    -0.0016     -0.0016
2014     0.0001     -0.0015
2015     0.0025      0.0025
2016    -0.0003     -0.0003
2017     0.0023      0.002
2018     0.0002      0.0002
您可以看到2015年AggCol的问题是错误的


请注意,我认为这些答案都是很好的尝试,当涉及到缺口/孤岛时,会展示一些真正的技能/代码。我并不是简单地试图通过攻击来提高帖子的质量。

您使用的是什么版本的SQL Server?您可以使用SQL Server中的查询来实现这一点,但它需要递归CTE。2012,我同意CTE的。。。有dbo访问权限,所以可以做任何需要的事情。在值为正之前,你是指表中的值还是累积的总和?直到表中的值为正。先生,你是一个天生的怪物!我的意思是,尽可能以最恭维的方式,因为我被你回答这个问题的速度吓坏了!非常感谢@用户3486773,也谢谢您提出的有趣的问题。这是一个很好的尝试,适用于提供的测试数据,但当需要多个正值才能使运行和成为正数时,它会出现故障。e、 g.将2014年更改为.0001,而2015年将出现错误的值。这是一次伟大的尝试,可用于提供的测试数据,但当需要多个正值才能使运行和成为正数时,它会出现故障。e、 g.将2014年更改为.0001,2015年的现值将错误。
Year    Value        AggCol
2013    -0.0016     -0.0016
2014     0.0001     -0.0015
2015     0.0025      0.0025
2016    -0.0003     -0.0003
2017     0.0023      0.002
2018     0.0002      0.0002