【问题标题】:sql pivot summarize table and compare rowssql pivot 汇总表并比较行
【发布时间】:2013-05-12 20:44:04
【问题描述】:

我有这三张桌子 由于 account 和 bounse 之间存在多对多关系,我想通过将当前月份的 bounse 与上个月相减来比较每个帐户的 bounse 与上个月的 bounse

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,使用 T-SQL 或 LINQ 查询

【问题讨论】:

  • 请确认您是否只有两个日期,因为您只想获取两个日期之间的差异。
  • +1 很好的解释..
  • 是的,我只有两个日期可以比较(当前月份和上个月),但我有很多日期详细信息存储在 tbl_detail 中

标签: sql linq tsql pivot


【解决方案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

【讨论】:

  • 谢谢你的回答,用第二种方法......'bounse's是一个表(bounseA,bounseB....... BounseN),我需要将bounse名称转换为列在结果上动态地
  • 你会做这样的动态 sql: 1. 查找不同的奖金 从奖金表中选择不同的奖金名称 2. 将它们放在 cte 中然后引用 3. 将它们插入另一个表,但将它们的语句更改为 '最大值(当 b.bonusname = ''' + temp.name + ''' 然后 detailvalue 结束时的情况)为 ' + b.bonusname。 4. 创建一个临时表并插入 select 'select a.id, d.detaile' 的第一部分 5. 执行一个 while 循环,在其中计算临时表中的行数 第 3 步并将新行插入步骤 4 中的表。 5. 现在插入 from 表达式并为 group by 进行动态插入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 2016-02-07
相关资源
最近更新 更多