2016-05-19 16 views
0

日付、通貨、国ごとの履歴cash_balancesを持つテーブルがあります。SQL:前月の最終営業日の2日目から値を取得

前の月の2番目の最終営業日の列 "cash_balance"の値を "cash_balance_last_month"という列に入力する必要があります。前月の2番目の最終日と定義されていますテーブル内のデータ。

ので、テーブルは次のようになります2016-30-03 3月の第二の最後の営業日であることを

report_date/currency/country/cash_balance/cash_balance_last_month 
2016-03-05/ USD / US / 110 /  NULL 
2016-03-05/ EUR / DE / 130 /  NULL 
2016-03-05/ EUR / FR / 240 /  NULL 
2016-02-05/ USD / US / 105 /  NULL 
2016-02-05/ EUR / DE / 125 /  NULL 
2016-02-05/ EUR / FR / 245 /  NULL 
2016-29-04/ USD / US / 100 /  NULL 
2016-29-04/ EUR / DE / 120 /  NULL 
2016-29-04/ EUR / FR / 250 /  NULL 
2016-28-04/ USD / US /  95 /  NULL 
2016-28-04/ EUR / DE / 115 /  NULL 
2016-28-04/ EUR / FR / 255 /  NULL 
... 
2016-30-03/ USD / US /  90 /  NULL 
2016-30-03/ EUR / DE / 117 /  NULL 
2016-30-03/ EUR / FR / 257 /  NULL 

注意。

表は次のようになります。

report_date/currency/country/cash_balance/cash_balance_last_month 
2016-03-05/ USD / US / 110 /  95 
2016-03-05/ EUR / DE / 130 /  115 
2016-03-05/ EUR / FR / 240 /  255 
2016-02-05/ USD / US / 105 /  95 
2016-02-05/ EUR / DE / 125 /  115 
2016-02-05/ EUR / FR / 245 /  255 
2016-29-04/ USD / US / 100 /  90 
2016-29-04/ EUR / DE / 120 /  117 
2016-29-04/ EUR / FR / 250 /  257 
2016-28-04/ USD / US /  95 /  90 
2016-28-04/ EUR / DE / 115 /  117 
2016-28-04/ EUR / FR / 255 /  257 
... 
2016-30-03/ USD / US /  90 /  NULL 
2016-30-03/ EUR / DE / 117 /  NULL 
2016-30-03/ EUR / FR / 257 /  NULL 

最初のエントリが、この例2016-30-03では、明らかに参照するために前月必要はありません。

"cash_balance_last_month"という列はどのように計算されますか?私は自分自身でそれを理解することができなかったし、私が解決策を考え出すのに役立つ関連する質問を見つけることもできなかった。

大変助かります。ありがとうございました!

+0

カレンダーテーブルはありますか?あなたがしなければ、 – Squirrel

+0

私はしないでください。 1つではありません。 – SSA

+1

カレンダーの日付に依存しているのではなく、表にデータがあると思われます。テーブル内のデータのrow_numberを計算し、年/月(および国?)順に日付descで区切って、指定された月-1のrow_number = 2の行から値を取得するだけです。 – dean

答えて

1
declare @table table 
(report_date datetime , currency varchar(3), country varchar(2), cash_balance int, cash_balance_last_month int) 
insert into @table 
values 
(cast('2016-05-03' as datetime), 'USD' , 'US' ,  110  ,  NULL), 
(cast('2016-05-03' as datetime), 'EUR' , 'DE' ,  130  ,  NULL), 
(cast('2016-05-03' as datetime), 'EUR' , 'FR' ,  240  ,  NULL), 
(cast('2016-05-02' as datetime), 'USD' , 'US' ,  105  ,  NULL), 
(cast('2016-05-02' as datetime), 'EUR' , 'DE' ,  125  ,  NULL), 
(cast('2016-05-02' as datetime), 'EUR' , 'FR' ,  245  ,  NULL), 
(cast('2016-04-29' as datetime), 'USD' , 'US' ,  100  ,  NULL), 
(cast('2016-04-29' as datetime), 'EUR' , 'DE' ,  120  ,  NULL), 
(cast('2016-04-29' as datetime), 'EUR' , 'FR' ,  250  ,  NULL), 
(cast('2016-04-28' as datetime), 'USD' , 'US' ,  95  ,  NULL), 
(cast('2016-04-28' as datetime), 'EUR' , 'DE' ,  115  ,  NULL), 
(cast('2016-04-28' as datetime), 'EUR' , 'FR' ,  255  ,  NULL), 
(cast('2016-03-31' as datetime), 'USD' , 'US' ,  10  ,  NULL), 
(cast('2016-03-31' as datetime), 'EUR' , 'DE' ,  10  ,  NULL), 
(cast('2016-03-31' as datetime), 'EUR' , 'FR' ,  10  ,  NULL), 
(cast('2016-03-30' as datetime), 'USD' , 'US' ,  90  ,  NULL), 
(cast('2016-03-30' as datetime), 'EUR' , 'DE' ,  117  ,  NULL), 
(cast('2016-03-30' as datetime), 'EUR' , 'FR' ,  257  ,  NULL) 

select t1.report_date,t1.currency,t1.country,t1.cash_balance, s.cash_balance as cash_balance_last_month 
from @table t1 
left join 
(
select t1.*, 
     year(t1.report_date) * 12 + month(t1.report_date) monthnum, 
     row_number() over(partition by year(t1.report_date) * 100 + month(t1.report_date), t1.country order by t1.report_date desc) rn 
from @table t1 
) s 
on s.monthnum = (year(t1.report_date) * 12 + month(t1.report_date)) - 1 
    and t1.country = s.country and t1.currency = s.currency 
    and s.rn = 2 
+0

英国にローカライズされた日付。トリックは行番号だけでなく月番号を計算することです。 –

+0

ありがとうございました!これは必要に応じて正確に機能しました – SSA

関連する問題