2013-05-12 92 views
1

我有這三個表 與帳戶和bounse之間的多對多關係,我想比較每個帳戶與上個月的bounse通過減去當前月與上個月的bounsesql pivot彙總表和比較行

tbl_account

account_id account_name 
----------- --------------------- 
1  Account1 
2  Account2 

tbl_bounse

bounse_id bounse_name 
----------- ------------- 
42   bounseA 
43   bounseB 
44   BounseC 

tbl_detail(連桿tbl_account和TBL之間表_bounse)

detail_accound_id detail_bounce_id detail_value   detail_id detail_date 
----------------- ---------------- -------------------- ----------- ----------- 
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 

,我想總結的結果作爲

accound_id  detail_date  BounseA  BounseB  BounseC 
-----------  -----------  -------  -------  -------  
1   2013-05-05  24000  150  23000 
1   2013-06-06  25000  150  25500 
1   differ date  1000   0  2500 
2   2013-05-05  20000  400  10000 
2   2013-06-06  23000  350  11000 
2   differ date  3000   -50  1000 

返回臨時表作爲

accound_id  detail_date  BounseA  BounseB  BounseC 
-----------  -----------  -------  -------  -------  
1   differ date  1000   0  2500 
2   differ date  3000   -50  1000 

我想要使用支點和動態SQL,但我不知道如何減去行並將減去的結果插入臨時表

SQL server 2008 r2,the qu使用T-SQL或LINQ的

+0

請確認您是否只有兩個日期,只要你想只得到兩個日期之間的差異。 – 2013-05-12 21:16:53

+0

+1對於很好的解釋。 – 2013-05-12 21:17:59

+0

是的,我只有兩個日期比較(當前月和上個月),但我有很多日期詳細信息存儲在tbl_detail – Fadi 2013-05-12 21:50:24

回答

1

我將使用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 
+0

謝謝你的回答,用第二種方法......'bounse's是一張桌子(bounseA,bounseB ....... BounseN),而且我需要將bounse名字轉換爲動態列結果 – Fadi 2013-05-13 07:34:22

+1

你會做如下的動態SQL:1.找到不同的獎金,從可選的獎勵名中選擇不同的獎勵名2.將它們放入一個cte然後參考3.將它們插入另一個表中,但將其語句更改爲'max(case when b.bonusname ='' '+ temp.name +'''then detailvalue end)as'+ b.bonusname。 4.創建一個臨時表並插入select'select a.id,d.detaile'的第一部分5.執行一個while循環,在其中執行臨時表第3步中的行計數,並將NEW行插入到表格。5.現在插入from表達式併爲group by做一個動態插入。 – djangojazz 2013-05-13 14:19:17