これは、期間テーブルを作成することで比較的簡単な方法で行うことができます。期間テーブルをアカウントテーブルと結合して、期間ごとにアカウントごとに1つの行を作成できます。
これが例です。いくつかの一時テーブルを設定しましょう。
create table #balance (
id int identity,
balance float,
date datetime,
aid int
)
create table #period (
id int identity,
startdt datetime,
enddt datetime
)
いくつかのテストデータを入力します。
insert into #yourtable (balance, date, aid) values (4,'2009-01-01',1)
insert into #yourtable (balance, date, aid) values (5,'2009-01-10',1)
insert into #yourtable (balance, date, aid) values (6,'2009-01-10',1)
insert into #yourtable (balance, date, aid) values (7,'2009-01-16',1)
insert into #yourtable (balance, date, aid) values (2,'2009-01-01',2)
insert into #yourtable (balance, date, aid) values (3,'2009-01-10',2)
insert into #yourtable (balance, date, aid) values (4,'2009-01-10',2)
insert into #yourtable (balance, date, aid) values (5,'2009-01-16',2)
insert into #period (startdt, enddt) values ('2009-01-01','2009-01-06')
insert into #period (startdt, enddt) values ('2009-01-06','2009-01-11')
insert into #period (startdt, enddt) values ('2009-01-11','2009-01-16')
insert into #period (startdt, enddt) values ('2009-01-16','2009-01-21')
それでは、すべての期間をクエリしてみましょう。
from #period p
期間が終了する前に、残高ごとに1行を追加します。
left join #balance b1 on
b1.date <= p.enddt
最初の結合からの残高と期間の終了の間の残高を検索します。
left join #balance b2 on
b2.aid = b1.aid
and b1.id < b2.id
and b2.date <= p.enddt
次に、その期間の最後の残高ではない行を除外します。
where
b2.aid is null
b2結合は基本的に「中間」値を検索し、IDがnullであると言うことで、中間行が存在しないことを示します。最終的なクエリは次のようになります。
select
b1.aid
, p.startdt
, b1.balance
from #period p
left join #balance b1 on
b1.date <= p.enddt
left join #balance b2 on
b2.aid = b1.aid
and b1.id < b2.id
and b2.date <= p.enddt
where
b2.aid is null
order by b1.aid, p.startdt
注:クエリは、後の日付の残高のIDが常に大きいことを前提としています。まったく同じ終了日で残高を調整する必要がない場合は、「b1.id<b2.id」を「b1.date<b2.date」に置き換えることができます。