连续行之间的计算

时间:2015-02-06 18:46:34

标签: sql sql-server

我有一个具有以下结构的表格,我需要在两个连续日期之间进行计算(比如减法)(给定可用日期)并在底部插入行来计算计算后列中0的数字,并计算0的百分比。

我遇到的主要问题是日期是随机的:长度是随机的,没有必要按顺序排列(我在另一个“select”语句中的临时表中有“排序依据”的问题,所以...我把它留给了排序,请帮助),而不是必要的完整(例如:在示例中缺少2015-01-04) 列长度​​是随机的:不必像示例中那样停在“组3”。

Date        group1  group2  group3...
2015-01-01  1       2       3
2015-01-05  1       1       NULL
2015-01-03  2       2       3
2015-01-04  3       4       1

需要进行的计算如下:

Date        group1  group2  group3...
2015-01-01  1-2     2-2     3-3
2015-01-03  2-3     2-4     3-1
2015-01-04  3-1     4-1     1-NULL

决赛桌必须是:

Date        group1  group2  group3...
2015-01-01  -1      0       0
2015-01-03  -1      -2       2
2015-01-04  2       3       NULL
count-zero  0       1       1
zero-perc   0       33.33   33.33

2 个答案:

答案 0 :(得分:0)

您可以使用LEAD窗口函数:

select
    Date,
    group1 - LEAD(group1) over(order by Date) as group1,
    group1 - LEAD(group2) over(order by Date) as group2,
    group1 - LEAD(group3) over(order by Date) as group3...
from YourTable

要动态执行此操作,请使用sys.tablessys.columns构建您的查询:

declare @sql nvarchar(max) = ''
select @sql = 'select Date,' + 
    (select c.name + ' - LEAD(' + c.name + ') over(order by Date) as ' + c.name +
        case row_number() over(order by c.column_id desc)
            when 1 then '' else ',' end
     from sys.columns c
     where object_id = t.object_id
         and c.name like 'group%'
     order by c.column_id asc
     for xml path('')) + ' from YourTable'
from sys.tables t
where t.name = 'YourTable'

exec(@sql)

答案 1 :(得分:0)

经典方法是对行进行编号,然后通过连续数字将它们连接起来。您的系统可能有其他选择:

with OrderedData as (
    select
        t1.*,
        /* assigned sequential numbers to the rows */
        (select count(*) from T as t2 where t2.Date <= t1.Date) as DateNumber,

        /* in sql server this may be preferable to a subquery */
        -- row_number() over (order by Date) as DateNumber

        /* finding the next date is another option that might seem clearer */
        (select min(t2.Date) from T as t2 where t2.Date > t1.Date) as NextDate
    from T as t1
)
select od1.Date, od2.group1 - od1.group1, od2.group2 - od1.group2, od2.group3 - od1.group3
from OrderedData as od1
    left outer join OrderedData as od2
        /* match up consecutive rows */
        on od2.DateNumber = od1.DateNumber + 1

但这并不能处理你的零行。