树形结构分析汇总

t1

id     parentid

m    a

n    a

e    m

f    m

x    f

y    f

z    b

 

t2

row    id      amount

1    a    13.00

2    b    20.00

3    e    20.00

4    f    20.00

5    x    20.00

6    y    20.00

7    z    20.00

8    e    12.00

9    x    11.00

10    f    13.00

 

如何按照结构
a
--m
---e
---f
----x
----y
--n
b
--z

 

如何得出如下结果:

 

row     id      amount

7    x    20.00

11    x    11.00

    x小计   31.00

8    y    20.00

    y小计   20.00

6    f    20.00

12    f    13.00

    f小计   84.00

5    e    20.00

10    e    12.00

    e小计   32.00

3    m    14.00

    m小计   130.00

4    n    13.00

    n小计   13.00

1    a    13.00

    a小计   156.00

9    z    20.00

    z小计   20.00

2    b    20.00

    b小计   40.00

    总计   196.00

 

 

 

---------------------------------

--  Author: liangCK 小梁

---------------------------------

 

--> 生成测试数据: @tb1

DECLARE @tb1 TABLE (id VARCHAR(1),parentid VARCHAR(1))

INSERT INTO @tb1

SELECT 'm','a' UNION ALL

SELECT 'n','a' UNION ALL

SELECT 'e','m' UNION ALL

SELECT 'f','m' UNION ALL

SELECT 'x','f' UNION ALL

SELECT 'y','f' UNION ALL

SELECT 'z','b'

 

--> 生成测试数据: @tb2

DECLARE @tb2 TABLE (row INT,id VARCHAR(1),amount NUMERIC(4,2))

INSERT INTO @tb2

SELECT 1,'a',13.00 UNION ALL

SELECT 2,'b',20.00 UNION ALL

SELECT 3,'m',14.00 UNION ALL

SELECT 4,'n',13.00 UNION ALL

SELECT 5,'e',20.00 UNION ALL

SELECT 6,'f',20.00 UNION ALL

SELECT 7,'x',20.00 UNION ALL

SELECT 8,'y',20.00 UNION ALL

SELECT 9,'z',20.00 UNION ALL

SELECT 10,'e',12.00 UNION ALL

SELECT 11,'x',11.00 UNION ALL

SELECT 12,'f',13.00

 

--SQL查询如下:

 

--2005

;WITH Liang AS

(

    SELECT

        id,

        parentid,

        Ancestors=parentid,

        PATH=CAST(parentid+'.'+id AS VARCHAR(MAX))

    FROM @tb1 AS A

    WHERE NOT EXISTS(

              SELECT *

              FROM @tb1

              WHERE A.parentid=id

          )

    UNION ALL

    SELECT

        A.id,

        A.parentid,

        B.Ancestors,

        CAST(B.PATH+'.'+A.id AS VARCHAR(MAX))

    FROM @tb1 AS A

        JOIN Liang AS B

            ON A.parentid=B.id

),

Liang1 AS

(

    SELECT * FROM Liang

    UNION ALL

    SELECT DISTINCT

        parentid,

        parentid,

        Ancestors=parentid,

        PATH=CAST(parentid AS VARCHAR(MAX))

    FROM @tb1 AS A

    WHERE NOT EXISTS(

              SELECT *

              FROM @tb1

              WHERE A.parentid=id

          )

),

Liang2 AS

(

    SELECT

        A.id,

        A.parentid,

        A.Ancestors,

        A.PATH,

        B.row,

        B.amount,

        RID=DENSE_RANK()

              OVER(ORDER BY Ancestors,LEN(PATH)-LEN(REPLACE(PATH,'.','')) DESC,A.id)

    FROM Liang1 AS A

        JOIN @tb2 AS B

            ON A.id=B.id

),

Liang3 AS

(

    SELECT

        id,

        row,

        min(PATH) AS PATH,

        SUM(amount) AS amount,

        MIN(rid) AS rid,

        GROUPING(row) AS grow

    FROM Liang2

    GROUP BY id,row

    WITH ROLLUP

    HAVING GROUPING(id)=0

),

Liang4 AS

(

    SELECT

        *

    FROM Liang3 AS A

        OUTER APPLY (SELECT SUM(amount) sumamount

                     FROM Liang3

                     WHERE PATH LIKE A.PATH+'%'

                         AND grow=1) AS B

)

SELECT

    row,

    id,

    amount

FROM(

    SELECT

        CASE WHEN grow=1 THEN '' ELSE RTRIM(row) END AS row,

        CASE WHEN grow=1 THEN id+'小计' ELSE id END AS id,

        CASE WHEN grow=1 THEN sumamount ELSE amount END AS amount,

        rid

    FROM Liang4

    UNION ALL

    SELECT

        '','合计',SUM(amount),99999999

    FROM @tb2

) AS A

ORDER BY rid

 

/*

row          id    amount

------------ ----- ---------------------------------------

7            x     20.00

11           x     11.00

             x小计  31.00

8            y     20.00

             y小计  20.00

5            e     20.00

10           e     12.00

             e小计  32.00

6            f     20.00

12           f     13.00

             f小计  84.00

3            m     14.00

             m小计  130.00

4            n     13.00

             n小计  13.00

1            a     13.00

             a小计  156.00

9            z     20.00

             z小计  20.00

2            b     20.00

             b小计  40.00

             合计   196.00

 

(22 行受影响)

 

*/

 

--这是钻钻写的2000方法:

create function f_isChild(@id varchar(8),@cid varchar(8))

returns bit

as

begin

  if(@id=@cid)

    return 1

 

  declare @t table(id varchar(8),parentid varchar(8))

 

  insert into @t select * from t1 where id=@cid

 

  while @@rowcount>0

  begin

    if exists(select 1 from @t where parentid=@id)

      return 1

   

    insert into @t

    select b.* from @t a,t1 b

    where b.id=a.parentid and not exists(select 1 from @t where id=b.id)

  end

 

  return 0

end

go

 

 

create function f_getLevel(@id varchar(8))

returns varchar(40)

as

begin

  declare @var varchar(40),@parentid varchar(8)

  set @var=right('000'+@id,4)

  while exists(select 1 from t1 where id=@id)

  begin

    select @var=right('000'+parentid,4)+@var,@parentid=parentid from t1 where id=@id

    set @id=@parentid

  end

 

  return @var

end

go

 

select

    t.row,case when t.nid=2 then t.id+'小计' else t.id end as id,t.amount

from

  (select *,1 as nid from t2

    union all

    select

        null as row,a.id,sum(b.amount) as amount,2 as nid

    from

        (select distinct id from t2) a,t2 b

    where

        dbo.f_isChild(a.id,b.id)=1

    group by

        a.id

    union all

    select null as row,'总计',sum(amount),3 as nid from t2

    ) t

order by

    (case when nid=3 then 2 else 1 end),dbo.f_getLevel(t.id) desc,t.id,nid

go

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值