获取符合条件的下一行

时间:2018-05-08 18:05:55

标签: sql-server

我目前有一个存储过程可以返回某人的总收入,并检查当前金额是否超出预期输入。

总收入是手动输入的,有时人们会输入错误的金额,比如加一个额外的0或忘记一个号码。

存储过程计算自上次输入以来的收入。预期会有某些事情,并且存储过程会告诉该行是否超出预期值(例如,如果值为负值)

我需要做什么“忽略”那些输入并根据下一行计算而没有错误。例如,在下面的查询中:

DECLARE @Table AS TABLE (
    [Date] DATETIME,
    [Name] VARCHAR(100),
    [TotalEarnings] DECIMAL(10,2),
    [PartialEarnings] DECIMAL(10,2),
    [ConsecultiveErrors] INT
);

INSERT INTO @Table VALUES ('20180510 00:00:00', 'John', 1000.00, NULL, 0);
INSERT INTO @Table VALUES ('20180509 00:00:00', 'John', 9000.00, -8000.00, 3);
INSERT INTO @Table VALUES ('20180508 00:00:00', 'John', 80.00, 8920.00, 2);
INSERT INTO @Table VALUES ('20180507 00:00:00', 'John', 700.00, -720.00, 1);
INSERT INTO @Table VALUES ('20180506 00:00:00', 'John', 600.00, 100.00, 0);
INSERT INTO @Table VALUES ('20180505 00:00:00', 'John', 5000.00, -4400.00, 2);
INSERT INTO @Table VALUES ('20180504 00:00:00', 'John', 400.00, 4600.00, 1);
INSERT INTO @Table VALUES ('20180503 00:00:00', 'John', 300.00, 100.00, 0);
INSERT INTO @Table VALUES ('20180502 00:00:00', 'John', 20.00, 180.00, 2);
INSERT INTO @Table VALUES ('20180501 00:00:00', 'John', 100.00, -80.00, 1);

SELECT
    [t].[Date],
    [t].[Name],
    [t].[TotalEarnings],
    [t].[PartialEarnings],
    [t].[ConsecultiveErrors]
FROM
    @Table AS [t]

我需要从第1天到第1天的行之间的差异计算平均值(第3天),每次给第1天和第2天100美元。

我怎样才能做到这一点?

[EDIT1]所以最后一列显示了序列中有错误的行数。他们使用它,因为误差是使用偏值计算的,而部分值是使用LAG / LEAD函数计算的。因此,一个错误的输入实际上可能导致两行或更多行被视为“错误”

1 个答案:

答案 0 :(得分:0)

您的描述有点混乱,但我认为这可以满足您的需求吗?

CTE使用条件运行sumConsecutiveErrors = 1中排序时将行ConsecutiveErrors = 0分组到DateValue(不要使用保留字等作为对象名称的Date订单。它还提供TotalEarnings作为第一行的否定或最后一行的正数,0否则,sum为您提供第一行和最后一行之间的差异在ErrorGroup

然后,您可以在PartialEarnings行中返回正确的ConsecutiveErrors = 0值,或者averageEarningsDiffence的{​​{1}}值。 1}}减去ErrorGroup(即:组内错误行的数量):

1

输出:

declare @t as table (
    DateValue datetime,
    Name varchar(100),
    TotalEarnings decimal(10,2),
    PartialEarnings decimal(10,2),
    ConsecutiveErrors int
);

insert into @t values ('20180510 00:00:00', 'John', 1000.00, NULL, 0);
insert into @t values ('20180509 00:00:00', 'John', 9000.00, -8000.00, 3);
insert into @t values ('20180508 00:00:00', 'John', 80.00, 8920.00, 2);
insert into @t values ('20180507 00:00:00', 'John', 700.00, -720.00, 1);
insert into @t values ('20180506 00:00:00', 'John', 600.00, 100.00, 0);
insert into @t values ('20180505 00:00:00', 'John', 5000.00, -4400.00, 2);
insert into @t values ('20180504 00:00:00', 'John', 400.00, 4600.00, 1);
insert into @t values ('20180503 00:00:00', 'John', 300.00, 100.00, 0);
insert into @t values ('20180502 00:00:00', 'John', 20.00, 180.00, 2);
insert into @t values ('20180501 00:00:00', 'John', 100.00, -80.00, 1);

with g as
(
    select DateValue
        ,Name
        ,TotalEarnings
        ,PartialEarnings
        ,ConsecutiveErrors
        ,sum(case when ConsecutiveErrors = 1 then 1 else 0 end) over (order by DateValue) as ErrorGroup
        ,case when ConsecutiveErrors = 1 then -TotalEarnings
                when ConsecutiveErrors = 0 then TotalEarnings
                else 0
                end as EarningsDifference
    from @t
)
select DateValue
        ,Name
        ,TotalEarnings
        ,PartialEarnings
        ,ConsecutiveErrors
        ,ErrorGroup
        ,case when ConsecutiveErrors = 0
                then PartialEarnings
                else sum(EarningsDifference) over (partition by ErrorGroup)
                    / (count(EarningsDifference) over (partition by ErrorGroup)-1)
                end as AverageEarnings
from g
order by DateValue