3

「実行中のパフォーマンス」のやや複雑な計算に、ウィンドウと CTE を使用して「Quirky Update」を使用する代わりの方法を考え出そうとしています。ランニング パフォーマンスの簡単な計算は、((1 + ランニング) * (1 + デイリー)) - 1 です。このランニングは、現在の行に対して更新し、次の行の計算で使用する必要があります。AssetID が変更されると、0 にリセットされます。私が見つけた唯一の代替手段は、exp(sum(log)) (コード サンプルに示されています) を使用することです。現実の世界では数値は正しいですが、Quirky Update を使用するとほぼ瞬時に使用するには遅すぎます。私のサンプルでは、​​毎日の計算をウィンドウ処理に置き換えていますが、実行中は現在の行を更新し、それを次の行の計算に反映させる必要があるため、実行中の計算を処理するためにウィンドウ処理と CTE を使用する方法が思いつきませんでした。したがって、私の試みは、風変わりな更新に似た更新ステートメントの変数を使用しており、それらは間違っています。たぶん、私が毎日計算している方法に似た方法がありますか?前もってありがとう、ロブ

if OBJECT_ID('tempdb..#DMVRunningPerformance') is not null
    drop table #DMVRunningPerformance

create table #DMVRunningPerformance (
    LongPosition_bt bit null,
    AssetID_in int null,
    Symbol_vc varchar(255),
    DayID_in int,
    Status_vc varchar(255) null,
    MV float,
    DailyPerf float null,
    RunningPerf float null)

    CREATE CLUSTERED INDEX [indexdown] ON #DMVRunningPerformance 
        (
            [LongPosition_bt] ASC,
            [AssetID_in] ASC,
            [DayID_in] DESC
        )
    WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

insert into #DMVRunningPerformance  
 values (1,100,'IBM',75006,NULL,201048.8987,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75005,NULL,200841.5658,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75004,NULL,200321.7043,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75003,NULL,201120.0467,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75002,NULL,201779.8805,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75001,NULL,201651.3917,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,100,'IBM',75000,NULL,201101.0320,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75006,NULL,805048.8987,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75005,NULL,801841.5658,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75004,NULL,804321.7043,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75003,NULL,809120.0467,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75002,NULL,801779.8805,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75001,NULL,801151.3917,NULL,NULL)
insert into #DMVRunningPerformance  
 values (1,200,'MSFT',75000,NULL,801901.0320,NULL,NULL)

-------------------  BEGIN Quirky Update   -------------------------------------    
declare @RunningPerformance as float=0
declare @AssetID_in int=-1,
        @DayID_in int=0,
        @LongPosition_bt bit=0,
        @Status_vc varchar(255)=NULL,
        @NewGroup_bt bit=1,
        @DailyPerformance float,
        @NDMarketValue float,
        @PDMarketValue float=0,
        @NDSymbol_vc varchar(255)='XXXXXXXXXX',
        @PDSymbol_vc varchar(255)='XXXXXXXXXX',
        @NDDayID_in int,
        @PDDayID_in int,
        @NDAssetID_in int=-1,
        @PDAssetID_in int=-1

update #DMVRunningPerformance
    set 
        @LongPosition_bt=LongPosition_bt,
        @NewGroup_bt=CASE WHEN @AssetID_in<>AssetID_in or @LongPosition_bt<>LongPosition_bt THEN 1 ELSE 0 END,
        @DailyPerformance=CASE WHEN @NewGroup_bt=1 THEN 0 ELSE
                            (@NDMarketValue-MV)/MV END,
        @RunningPerformance=CASE WHEN @NewGroup_bt=1 THEN 0 ELSE
                            ((1 + @RunningPerformance) * (1 + @DailyPerformance)) - 1 END
        ,DailyPerf=@DailyPerformance
        ,RunningPerf=@RunningPerformance
        ,@AssetID_in=AssetID_in
        ,@NDAssetID_in=AssetID_in
        ,@NDSymbol_vc=Symbol_vc
        ,@NDDayID_in=DayID_in
        ,@NDMarketValue=MV
FROM #DMVRunningPerformance OPTION (MAXDOP 1)

select 'this data is correct'
select * from #DMVRunningPerformance
-------------------  END Quirky Update   -------------------------------------  

-- reset performance
update #DMVRunningPerformance set DailyPerf=null, RunningPerf=NULL

-------------------  BEGIN windowing and CTE   -------------------------------------    
-- update daily perf with CTE
;WITH dailyCTE as
    (
    select LongPosition_bt,AssetID_in,Symbol_vc,DayID_in,PreviousAssetID,
        MV,
        DailyPerformance = CASE WHEN YesterdayMV IS NULL THEN 0 
                            ELSE (YesterdayMV - MV) / MV END
    FROM
        (
            select p.LongPosition_bt,p.AssetID_in,p.Symbol_vc,p.DayID_in,
                p.MV,
                lag(p.MV,1) over (Partition by LongPosition_bt,AssetID_in
                                    order by DayID_in desc) as YesterdayMV,
                lag(p.AssetID_in,1) over (Partition by LongPosition_bt,AssetID_in
                                    order by DayID_in desc) as PreviousAssetID
                from #DMVRunningPerformance p
        ) p1
    )
    Update #DMVRunningPerformance 
        set DailyPerf=dailyCTE.DailyPerformance,
        @NewGroup_bt=CASE WHEN PreviousAssetID is null THEN 1 ELSE 0 END,
        @RunningPerformance=CASE WHEN PreviousAssetID is null THEN DailyPerformance ELSE
                            ((1 + @RunningPerformance) * (1 + DailyPerformance)) - 1 END,
        RunningPerf=@RunningPerformance
        from dailyCTE join #DMVRunningPerformance d
            on dailyCTE.LongPosition_bt=d.LongPosition_bt and dailyCTE.AssetID_in=d.AssetID_in and dailyCTE.DayID_in=d.DayID_in

select 'this data daily is correct, running is incorrect'

select * from #DMVRunningPerformance

-- alternate method for running perf
-- works but for realworld data takes orders of magnitude longer than quirky update
if 1=2
select 
    dr.AssetID_in,dr.LongPosition_bt,dr.DayID_in,dr.MV,dr.DailyPerf-1 as DailyPerformance,
    RunningPerformance_fl = exp((
                    select
                        sum(log(DailyPerf))
                    from
                        #DMVRunningPerformance
                    where
                        AssetID_in=dr.AssetID_in and LongPosition_bt=dr.LongPosition_bt and
                        DayID_in >= DR.DayID_in)) - 1
 from #DMVRunningPerformance dr
    order by
        dr.assetid_in,DR.DayID_in desc

-------------------  END windowing and CTE   -------------------------------------  



drop table #DMVRunningPerformance
4

1 に答える 1