1

I have this three table with many-to-many relation between account and bounse , i want to compare the bounse for each account with the previous month by subtract current month's bounse with the previous month

tbl_account

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

tbl_bounse

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

tbl_detail ( the link table between tbl_account and 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

and I want to summarize the result as

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

returned Temp Table as

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

i'm trying to use pivot and dynamic sql but i don't know how to subtract the rows and insert the result of subtracting into temp table

SQL server 2008 r2 , the query using T-SQL or LINQ

4

1 回答 1

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
于 2013-05-13T00:14:17.847 回答