我將使用CTE來執行樞軸,然後使用窗口函數來動態獲取最新的日期,或者添加一個變量來潛在地比較過去的月份。例子是自我解壓與表變量,所以如果你有SQL Management Studio中2008或更高版本,它將運行爲的是:
declare @account table (id int identity, name varchar(16));
declare @bonus table (id int identity(42,1), bonusname varchar(16));
declare @detail table (accountId int, bonusid int, detailvalue int, detailid int, detaildate date);
insert into @account values ('Account1'),('Account2');
insert into @bonus values ('bonusA'),('bonusB'),('BonusC');
insert into @detail values (1, 42, 24000, 158981, '2013-05-05')
,(1, 42, 25000, 159113 ,'2013-06-06')
,(1, 43, 150, 158982 ,'2013-05-05')
,(1, 43, 150, 159114 ,'2013-06-06')
,(1, 44, 23000, 158983 ,'2013-05-05')
,(1, 44, 25150, 159115 ,'2013-06-06')
,(2, 42, 20000, 159025 ,'2013-05-05')
,(2, 42, 23000, 159157 ,'2013-06-06')
,(2, 43, 400, 159026 ,'2013-05-05')
,(2, 43, 350, 159158 ,'2013-06-06')
,(2, 44, 10000, 159021 ,'2013-05-05')
,(2, 44, 11000, 159159 ,'2013-06-06')
;
-- Method 1 determines the current month and year by finding greatest date in your table, there is an issue with this method if you want to see other months.
with cte as
(
select
a.id
, d.detaildate
-- perform pivots based on id
, max(case when b.bonusname = 'BonusA' then detailvalue end) as BonusA
, max(case when b.bonusname = 'BonusB' then detailvalue end) as BonusB
, max(case when b.bonusname = 'BonusC' then detailvalue end) as BonusC
-- find the maximum date with a windowed function changing scope to group by (partition by) the identifier of the account
, max(d.detaildate) over(partition by a.id) as MaxDate
from @account a
join @detail d on a.id = d.accountId
join @bonus b on d.bonusid = b.id
group by
a.id
, d.detaildate
)
select
id
, max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) = Month(detailDate) then BonusA end) -
max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) - 1 = Month(detailDate) then BonusA end) as BonusADif
, max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) = Month(detailDate) then BonusB end) -
max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) - 1 = Month(detailDate) then BonusB end) as BonusBDif
, max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) = Month(detailDate) then BonusC end) -
max(case when Year(MaxDate) = Year(detaildate) and Month(MaxDate) - 1 = Month(detailDate) then BonusC end) as BonusCDif
from cte
group by id
;
-- Method 2 determines the current month and year by YOU listing a variable, this offers more flexibility in the future.
-- You could create a function or proc off of this for even more functionality
declare @MaxDate date = '6-1-2013';
with cte as
(
select
a.id
, d.detaildate
-- perform pivots based on id
, max(case when b.bonusname = 'BonusA' then detailvalue end) as BonusA
, max(case when b.bonusname = 'BonusB' then detailvalue end) as BonusB
, max(case when b.bonusname = 'BonusC' then detailvalue end) as BonusC
-- find the maximum date with a windowed function changing scope to group by (partition by) the identifier of the account
from @account a
join @detail d on a.id = d.accountId
join @bonus b on d.bonusid = b.id
group by
a.id
, d.detaildate
)
select
id
, max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) = Month(detailDate) then BonusA end) -
max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) - 1 = Month(detailDate) then BonusA end) as BonusADif
, max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) = Month(detailDate) then BonusB end) -
max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) - 1 = Month(detailDate) then BonusB end) as BonusBDif
, max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) = Month(detailDate) then BonusC end) -
max(case when Year(@MaxDate) = Year(detaildate) and Month(@MaxDate) - 1 = Month(detailDate) then BonusC end) as BonusCDif
from cte
group by id
請確認您是否只有兩個日期,只要你想只得到兩個日期之間的差異。 – 2013-05-12 21:16:53
+1對於很好的解釋。 – 2013-05-12 21:17:59
是的,我只有兩個日期比較(當前月和上個月),但我有很多日期詳細信息存儲在tbl_detail – Fadi 2013-05-12 21:50:24