2014-08-28 4 views
0

나는 다음과 같은 정보를 가지고있는 (베이스) 테이블이 :SQL : 쓰레기통에 집계 크기

order_id int 
timestamp datetime 
action  char(1)  --i=inserted, c=corrected, r=removed 
shares  int 

그것은 시스템 (ITS ORDER_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 

순서 11:10부터 다시 10시 0분 0초 및 10시 50분 20초에서 활성이고 : 예를 사용 다음과 같은 순서의 수명은 : 10 및 11:12:10

시스템에서 이러한 주문이 1000 건이며 막대 그래프/버켓으로 5 분으로 나누어 진 시계열에서 활성 상태 인 막대 그래프를 플로팅해야합니다. 주어진 주문에 대한 공유 수가 samenter code heree bin에서 두 번 이상 변경되면 공유를 평균화해야합니다. 05-10 : 10에 상기 한 예에서와 같이 그와

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 

기대 값 : 1000 900 800 900

교체 avg'd 수 빈 10 여기서 더 복잡한 예제 출력 :

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 

미리 도움을 주셔서 감사합니다.

+0

예상 입력 결과 데이터를 게시 할 수 있습니까? –

+0

제안 주셔서 감사합니다, @JaugarChang. 게시 내용을 조금 변경하고보다 포괄적 인 예와 예상 결과를 추가했습니다. –

답변

0

이것은 단순히 5 정수가 분할 된 기본 시간으로부터 분의 시간 차이 일 수 버킷 ID별로 그룹화 Running Sum problem in SQL Server (공유 이력에 의한 MS 또는베이스, 하나)의 변형이다. 그래서 같은 것을 할 것입니다 :

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 

이제 우리는 실행 합계를 수행 할 수있는 클러스터 된 인덱스 순서대로 #T 처리하기 위해 SQL 서버를 기발한 갱신를 사용합니다.

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 
+0

감사합니다 Pieter, (귀하의 Sybase에 대한 몇 가지 수정과 함께) 귀하의 솔루션을 노력하고있어하지만 난 3 질문 : 그게 뭔지 NUMBERS/TALLY 테이블에 대해 얘기하고, 2) 내가 할 수있는 구문 오류가 있어요 ' 'top top 1 i.shares' 행에서 해결하십시오 :'키워드 'top'근처의 구문이 틀립니다. msg 102, Level 15, 주 181', 3) Sybase에서 기발한 업데이트가 필요합니까? –

+0

@jeromeso : ** 숫자 표 ** : http://dba.stackexchange.com/questions/11506/why-are-numbers-tables-invaluable 및 http://sqlblog.com/blogs/adam_machanic/archive/2006 /07/12/you-require-a-number-table.aspx. 예, 기발한 업데이트는 SYBASE에서 여전히 작동해야합니다. SYBASE와 MS SQL Server의 분리를 선행하기 때문입니다. 구문 오류가 발생하면 ** TOP 1 ** 대신 ** FIRST **를 시도하십시오 (http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00801.1510에 따라). /html/iqrefso/X315771.htm) –

+0

SQL 솔루션으로 게임을 한 후에 Perl 구현보다 속도가 느리다는 것을 깨달았습니다. 제안에 감사드립니다, @PieterGeedkens! 나는 꽤 배우게된다. –