SQL:将大小聚合到容器中

SQL:将大小聚合到容器中,sql,sap-ase,Sql,Sap Ase,我有一个(Sybase)表,其中包含以下信息: order_id int timestamp datetime action char(1) --i=inserted, c=corrected, r=removed shares int 它跟踪系统中与订单(由其订单id标识)关联的共享。 举例来说,订单的有效期如下所示: timestamp action shares 10:00:00 i 1000

我有一个(Sybase)表,其中包含以下信息:

 order_id   int   
 timestamp  datetime   
 action     char(1)      --i=inserted, c=corrected, r=removed   
 shares      int
它跟踪系统中与订单(由其订单id标识)关联的共享。 举例来说,订单的有效期如下所示:

  timestamp action  shares      
  10:00:00  i       1000     -- initial Insert    
  10:06:30  c       900      -- one Change    
  10:07:12  c       800    
  10:50:20  r       800      -- Removal    
  11:10:10  i       600      -- 2nd Insert    
  11:12:10  r       600
在上面的示例中,订单从10:00:00和10:50:20起激活,从11:10:10和11:12:10再次激活

我在系统中有1000个这样的订单,我需要用柱状图绘制一个时间序列中有多少个股票处于活动状态,分为5分钟的仓位/桶。 如果给定订单的股票数量在此处的samenter代码内变化不止一次,我需要对股票进行平均;如上述10:05-10:10箱中的示例所示,其中1000、900和800可以平均为900

下面是一个更复杂的示例:

1, "20140828 10:00:00",  "i", 1000
1, "20140828 10:06:00",  "c",  900
1, "20140828 10:07:12",  "c",  500
1, "20140828 10:10:10",  "c",  400
1, "20140828 10:20:20",  "r",  400
1, "20140828 10:30:10",  "i",  300
1, "20140828 10:32:10",  "r",  300

2, "20140828 09:51:00",  "i",  500
2, "20140828 10:08:30",  "r",  500

3, "20140828 10:10:00",  "i", 1000
3, "20140828 10:11:20",  "r", 1000
其预期产出:

10:00:00 1500
10:05:00 1300
10:10:00 1450
10:15:00 400
10:20:00 400
10:25:00 0
10:30:00 300
10:35:00 0
10:40:00 0
10:45:00 0
10:50:00 0
10:55:00 0

提前感谢您的帮助。

这是基于(MS或Sybase,由于共享历史)的一个变体,按bucket ID分组,它可以是基本时间整数除以5的时间差(以分钟为单位)。这样做可以:

create table #t(
    BucketNo    int not null primary key clustered,
    Activity    int not null,
    Active      int not null
);

-- pre-aggregate activity data
-- assumes prior existence of a zero-based NUMBERS or TALLY table
insert #t(BucketNo,Activity,Active) 
select 
     N
    ,isnull(Activity,0)
    ,0
from NUMBERS 
left join (
    select
         datediff(mm,0,TimeStamp) / 5 as BucketNo
        ,case action when 'i' then +1
                          'r' then -1
         end * shares          as Activity
        ,0 as Active  
    from  ActivityTable
    where action <> 'c'
    group by            datediff(mm,0,TimeStamp) / 5 

    union all

    select
         datediff(mm,0,TimeStamp) / 5 as BucketNo
        ,case action when 'i' then +1
                          'r' then -1
         end * shares
         - (  select top 1 i.shares 
              from ActivityTable i
              where i.order_id = c.order_id  and  i.TimeStamp > c.TimeStamp
              order by i.TimeStamp desc
           ) as Activity
        ,0 as Active  
    from ActivityTable as c
    where c.action  = 'c         
    group by            datediff(mm,0,TimeStamp) / 5 
) data on data.BucketNo = N
where N < 24 * 12; -- 5 minute buckets per day

您能发布示例输入数据的预期输出结果吗?谢谢您的建议,@JaugarChang。我对我的帖子做了一些修改,添加了一个更全面的示例和预期输出。谢谢Pieter,我正在尝试您的解决方案(对Sybase进行了一些修改),但我有3个问题:1)您正在谈论的数字/理货表是什么,2)我在
select top 1 I.shares
line:
关键字“top”附近出现语法错误,无法解决该语法错误。Msg 102,15级,状态181
,3)奇怪的更新会在Sybase中起作用吗?@jeromeso:Numbers table:and。是的,奇怪的更新应该在SYBASE中仍然有效,因为它早于SYBASE和SQL Server的MS风格的分离。关于语法错误,请先尝试而不是前1(按照),在使用SQL解决方案后,我意识到它比我的Perl实现慢,因此我继续使用Perl。谢谢你的建议,@PieterGeedkens!我学到了不少。
declare @Shares   int = 0,
        @BucketNo int = 0;

-- `quirky update` peculiar to SQL Server
update #t
   set @Shares = Shares 
               = case when BucketNo = @BucketNo
                      then @Shares + Activity
                      else 0
                 end,
       @BucketNo = BucketNo
from #t with (TABLOCKX) -- not strictly necessary when using a temp table.
option (MAXDOP 1);      -- prevent parallelization of query

select BucketNo, Active from #t order by BucketNo
go