2016-11-06 11 views
0

私は2つの他の組み合わせを使用して集計テーブルを作成しようとしています。最近のレコードと2番目の最近のレコードでテーブルを更新する方法

フィード表A:

PrimaryKey, Score, DateField 
1, 50, 1/1/2016 
2, 12, 1/1/2016 
1, 75, 1/12/2016 
1, 80, 1/15/2016 
2, 35, 1/16/2016 

期待結果(表B):レコード1、80において

PrimaryKey, Score, LastScore, OtherFields... 
1, 80, 75, data... 
2, 35, 12, data... 

は、最新のレコード、75は第2の最新のレコードです。表Bのすべてのレコードについて、これがルールです。

;with cte as 
(
    select 
     PrimaryKey, 
     row_number() over(partition by PrimaryKey order by DateField desc) RowNumber 
    from 
     TableA 
) 

条件は日常私は、このようなステートメントを使用してい

表Aによって更新されます25Million表Aのレコード、および表B Bで250Millionレコードの上にありますということです

しかし、私の問題は、1つのマッチで最初の列を設定する方法と2つ目の列を別のものに設定する方法の問題があることです。

これを行うにはもっと簡単な方法がありますか?私は数日ではなく、数時間でこれを実行することを望んでいます。

ありがとうございました。

答えて

1

一つの方法は、条件付きの集約使用しています。その後、SQL Serverのバージョン> = 2012場合

with a as (
     select a.PrimaryKey, 
      max(case when seqnum = 1 then score end) as score, 
      max(case when seqnum = 2 then score end) as score_previous 
     from (select a.*, 
        row_number() over (partition by PrimaryKey order by DateField desc) as seqnum 
      from TableA a 
      ) a 
     where seqnum <= 2 -- This should help performance of the `group by` 
     group by a.PrimaryKey 
    ) 
select b.*, a.score, a.score_previous 
from b join 
    a 
    on b.primarykey = a.primarykey; 
+0

あなたはCTEで 'WHERE a.seqnumを<= 2 'を追加する必要があり、私はSQL Serverが自動的にそれを行うには十分にスマートであると仮定しないでください。 – dnoeth

+0

Gordonありがとうございます。更新セクションはどのように機能しますか? – arcee123

+0

@dnoeth - あなたはパフォーマンスの権利を意味しましたか? –

1

を:

declare @t table(PrimaryKey int, Score int, DateField date); 

insert into @t values 
    (1, 50, '2016-01-01'), 
    (2, 12, '2016-01-01'), 
    (1, 75, '2016-01-12'), 
    (1, 80, '2016-01-15'), 
    (2, 35, '2016-01-16'); 

select top 1 with ties 
    PrimaryKey, 
    Score, 
    LastScore = LAG (Score, 1, null) over (partition by PrimaryKey order by DateField), 
    DateField 
from 
    @t 
order by 
    row_number() over(partition by PrimaryKey order by DateField desc); 

編集:私はあなたが右の理解場合、更新は次のようになります。

declare @t table(PrimaryKey int, Score int, LastScore int, DateField date); 

insert into @t 
    (PrimaryKey, Score, DateField) 
values 
    (1, 50, '2016-01-01'), 
    (2, 12, '2016-01-01'), 
    (1, 75, '2016-01-12'), 
    (1, 80, '2016-01-15'), 
    (2, 35, '2016-01-16'); 


with cte as 
(
    select 
     PrimaryKey, 
     Score, 
     LastScore = LAG (Score, 1, null) 
         over (partition by PrimaryKey order by DateField), 
     DateField 
    from 
     @t 
) 
update t set 
    LastScore = cte.LastScore 
from 
    @t t 
    inner join cte on cte.PrimaryKey = t.PrimaryKey 
        and cte.DateField = t.DateField    
       -- and cte.Score = t.Score 
where 
    t.LastScore is null and cte.LastScore is not null; 

クエリを高速化するには、あなたは両方のテーブルのインデックスを持っていることを確認:

create nonclustered index IX_PrimaryKey_DateField on TableA 
(
    PrimaryKey asc, 
    DateField asc 
) 
include (Score); 

GO 

create nonclustered index IX_PrimaryKey_DateField on TableB 
(
    PrimaryKey asc, 
    DateField asc 
) 
include (Score, LastScore) 
where LastScore is null; 
+0

HI @Vadim。どうもありがとうございます。これをアップデートに結びつけることはできますか? – arcee123

+0

もう少し速いので、他のクエリを使用しましたが、インデックスの提案が使用されました。どうもありがとう。 – arcee123

関連する問題