业务数据库是sql server 2000
有张缴费表,数据量为百万级别的,
单据号码是不连续的并且会有断号,缺号的,金额也是不一定的,
我为了演示方便把单据号码排了序,金额也大部分固定为168.00单据号码  缴费金额 缴费日期
000001  168.00 2010-01-12
000002  168.00 2010-01-13
000003  168.00 2010-01-14
000004  168.00 2010-02-12
000005  168.00 2010-03-12
000006  168.00 2010-04-12
000007  168.00 2010-03-12
000008  168.00 2010-03-12
000009  168.00 2010-03-12000012  168.00 2010-03-12
000013  168.00 2010-03-12
000014  168.00 2010-03-12
000015  168.00 2010-04-12000023  168.00 2010-09-12000033  100.00 2010-04-12
000034  200.00 2010-03-12
000035  200.00 2010-03-12
现在要做个报表统计,要显示成按单据号码段分开,先得到单据数量,再按每个月分开算出金额,有的单据有的月份是不一有的就不显示的,请问各位大大有好的高效算法或者函数么?单据起始号  单据结束号    单据数量  开具金额      开具月份
000001  000009  9  504.00 1月
168.00 2月
672.00 3月
168.00 4月000012  000015  4  504.00 3月
168.00 4月

000023  000023  1  168.00 9月000033  000035  3  400.00 3月
100.00 4月

解决方案 »

  1.   

    http://www.3lian.com/edu/2011/03-13/4382.html
      

  2.   

    你先吧连续字段查找出来,然后再弄http://www.3lian.com/edu/2011/03-13/4382.html
      

  3.   

    -->测试数据
    if object_id('[tb]') is not null drop table [tb]
    go
    create table [tb]([单据号码] varchar(6),[缴费金额] numeric(5,2),[缴费日期] datetime)
    insert [tb]
    select '000001',168.00,'2010-01-12' union all
    select '000002',168.00,'2010-01-13' union all
    select '000003',168.00,'2010-01-14' union all
    select '000004',168.00,'2010-02-12' union all
    select '000005',168.00,'2010-03-12' union all
    select '000006',168.00,'2010-04-12' union all
    select '000007',168.00,'2010-03-12' union all
    select '000008',168.00,'2010-03-12' union all
    select '000009',168.00,'2010-03-12' union all
    select '000012',168.00,'2010-03-12' union all
    select '000013',168.00,'2010-03-12' union all
    select '000014',168.00,'2010-03-12' union all
    select '000015',168.00,'2010-04-12' union all
    select '000023',168.00,'2010-09-12' union all
    select '000033',100.00,'2010-04-12' union all
    select '000034',200.00,'2010-03-12' union all
    select '000035',200.00,'2010-03-12'
     
    -->查询
    ;with test1 as(
    select px=row_number() over(order by getdate()),* 
    from [tb] t 
    where not exists(select * from tb where 单据号码=t.单据号码-1)
    ),
    test2 as(
    select px=row_number() over(order by getdate()),* 
    from [tb] t 
    where not exists(select * from tb where 单据号码=t.单据号码+1)
    ),
    test3 as(
    select a.单据号码 单据起始号,b.单据号码 单据结束号 
    from test1 a,test2 b 
    where a.px=b.px
    ),
    test4 as(
    select px=row_number() over(partition by b.单据起始号 order by month(a.缴费日期)),
    b.单据起始号,b.单据结束号, 
    count(1) 单据数量,sum(缴费金额) 开具金额,ltrim(month(a.缴费日期))+'月' 开具月份
    from tb a 
    join test3 b on a.单据号码 between b.单据起始号 and 单据结束号
    group by b.单据起始号,b.单据结束号,month(缴费日期)
    )
    select 单据起始号=case when px=1 then 单据起始号 else '' end,
    单据结束号=case when px=1 then 单据结束号 else '' end, 
    单据数量=case when px!=1 then '' else ltrim((select sum(单据数量) from test4 where 单据起始号=t.单据起始号)) end,
    开具金额,开具月份
    from test4 t/**
    单据起始号  单据结束号  单据数量         开具金额                                    开具月份
    ------ ------ ------------ --------------------------------------- --------------
    000001 000009 9            504.00                                  1月
                               168.00                                  2月
                               672.00                                  3月
                               168.00                                  4月
    000012 000015 4            504.00                                  3月
                               168.00                                  4月
    000023 000023 1            168.00                                  9月
    000033 000035 3            400.00                                  3月
                               100.00                                  4月(9 行受影响)
    **/
      

  4.   


    1、连续号码段及统计的SQL我已经写好(是wufeng4552大大帮忙的,见下面)
    2、现在就是分月统计 不知道该如何写
    3、您的那个网页只是连续号码段的取号
    if not object_id('Tempdb..#tmp') is null
        drop table #tmp
    Go
    Create table #tmp([发票号码] nvarchar(6),[缴费金额] decimal(18,2))
    Insert #tmp
    select N'000001',168.00 union all
    select N'000002',168.00 union all
    select N'000003',168.00 union all
    select N'000004',168.00 union all
    select N'000005',168.00 union all
    select N'000006',168.00 union all
    select N'000007',168.00 union all
    select N'000008',168.00 union all
    select N'000009',168.00 union all
    select N'000012',168.00 union all
    select N'000013',168.00 union all
    select N'000014',168.00 union all
    select N'000015',168.00 union all
    select N'000023',168.00 union all
    select N'000033',100.00 union all
    select N'000034',200.00 union all
    select N'000035',200.00
    Go
    select min(t.[发票号码])发票起始号,
           max(t.[发票号码])发票结束号,
           count(*)发票张数,
           sum([缴费金额])发票合计金额
    from(
    select [发票号码],
           cnt=cast([发票号码] as int)-(select count(*)from #tmp n where m.[发票号码]>n.[发票号码]),
           [缴费金额]
    from #tmp m
    )t group by cnt
    /*
    发票起始号  发票结束号  发票张数        发票合计金额
    ------ ------ ----------- ---------------------------------------
    000001 000009 9           1512.00
    000012 000015 4           672.00
    000023 000023 1           168.00
    000033 000035 3           500.00(4 row(s) affected)
    */
      

  5.   


    这位大大 SQL2000不支持with啊,谢谢,有其他好的办法么
      

  6.   

    -->查询
    select 发票起始号,发票结束号,发票张数,sum(缴费金额) 开具金额,ltrim(month(缴费日期))+'月' 开具月份
    from
    (
    select min(t.[发票号码])发票起始号,
           max(t.[发票号码])发票结束号,
           count(*)发票张数,
           sum([缴费金额])发票合计金额
    from(
    select [发票号码],
           cnt=cast([发票号码] as int)-(select count(*)from tb n where m.[发票号码]>n.[发票号码]),
           [缴费金额]
    from tb m
    )t group by cnt
    ) a
    join tb b on b.发票号码 between a.发票起始号 and a.发票结束号
    group by 发票起始号,发票结束号,发票张数,month(缴费日期)
    格式可以通过前台程序来调,或者使用临时表
      

  7.   

    create table [#tb]([单据号码] varchar(6),[缴费金额] numeric(5,2),[缴费日期] datetime)
    insert [#tb]
    select '000001',168.00,'2010-01-12' union all
    select '000002',168.00,'2010-01-13' union all
    select '000003',168.00,'2010-01-14' union all
    select '000004',168.00,'2010-02-12' union all
    select '000005',168.00,'2010-03-12' union all
    select '000006',168.00,'2010-04-12' union all
    select '000007',168.00,'2010-03-12' union all
    select '000008',168.00,'2010-03-12' union all
    select '000009',168.00,'2010-03-12' union all
    select '000012',168.00,'2010-03-12' union all
    select '000013',168.00,'2010-03-12' union all
    select '000014',168.00,'2010-03-12' union all
    select '000015',168.00,'2010-04-12' union all
    select '000023',168.00,'2010-09-12' union all
    select '000033',100.00,'2010-04-12' union all
    select '000034',200.00,'2010-03-12' union all
    select '000035',200.00,'2010-03-12'select isnull(a.单据起始号,'') as 单据起始号,isnull(a.单据结束号,'')as 单据结束号,isnull(a.单据数量,'') as 单据数量,b.开具金额,ltrim(b.开具月份)+'月' as 开具月份 from
    (
    select ID=row_number() over(order by (select 1)),left(right(单据号码,2),1) as type, min(单据号码) as 单据起始号,
    max(单据号码) as 单据结束号,count(*) as 单据数量 from #tb  group by left(right(单据号码,2),1)
    )a right join
    (
    select ID=row_number() over(partition by left(right(单据号码,2),1)   order by left(right(单据号码,2),1)),sum(缴费金额) as 开具金额, left(right(单据号码,2),1) as type ,month(缴费日期)as 开具月份 
    from #tb group by left(right(单据号码,2),1),month(缴费日期)
    )b
    on a.type= b.type and b.id =1 
    /*
    单据起始号  单据结束号  单据数量        开具金额                                    开具月份
    ------ ------ ----------- --------------------------------------- --------------
    000001 000009 9           504.00                                  1月
                  0           168.00                                  2月
                  0           672.00                                  3月
                  0           168.00                                  4月
    000012 000015 4           504.00                                  3月
                  0           168.00                                  4月
    000023 000023 1           168.00                                  9月
    000033 000035 3           400.00                                  3月
                  0           100.00                                  4月(9 row(s) affected)
    */
      

  8.   


    select  isnull(a.单据起始号,'') as 单据起始号,isnull(a.单据结束号,'')as 单据结束号,isnull(ltrim(a.单据数量),'') as 单据数量,b.开具金额,ltrim(b.开具月份)+'月' as 开具月份 from
    (
    select ID=row_number() over(order by (select 1)),left(right(单据号码,2),1) as type, min(单据号码) as 单据起始号,
    max(单据号码) as 单据结束号,count(*) as 单据数量 from #tb  group by left(right(单据号码,2),1)
    )a right join
    (
    select ID=row_number() over(partition by left(right(单据号码,2),1)   order by left(right(单据号码,2),1)),sum(缴费金额) as 开具金额, left(right(单据号码,2),1) as type ,month(缴费日期)as 开具月份 
    from #tb group by left(right(单据号码,2),1),month(缴费日期)
    )b
    on a.type= b.type and b.id =1 
    稍微做下修改
      

  9.   


    2000下先插入2个临时表然后在又连接----SQL 2000select left(right(单据号码,2),1) as type, min(单据号码) as 单据起始号,
    max(单据号码) as 单据结束号,count(*) as 单据数量  into #t1 from #tb  group by left(right(单据号码,2),1)
    select ID=identity(int,1,1),sum(缴费金额) as 开具金额, left(right(单据号码,2),1) as type ,month(缴费日期)as 开具月份 into #t2
    from #tb group by left(right(单据号码,2),1),month(缴费日期)select isnull(a.单据起始号,'') as 单据起始号,isnull(a.单据结束号,'')as 单据结束号,isnull(ltrim(a.单据数量),'') as 单据数量,b.开具金额,ltrim(b.开具月份)+'月' as 开具月份 
    from #t1 a right join #t2 b on a.type = b.type and b.id =(select min(id) from #t2 where type = b.type) order by b.type , b.开具月份
      

  10.   

    那看样子是我理解错了不过如果是这样的话只要在上面的基础上添加一步就可以了也就是自己先加一个type字段明天给写个吧
      

  11.   

    那就再按月份分组,然后求出该月份的总金额
    你的月份金额应该和连续字段没什么关系吧?
    select sum(缴费金额), datepart(mm,缴费日期) as 月份 from tablename group by 月份 
      

  12.   

    select sum(缴费金额), datepart(mm,缴费日期) as 月份 from tablename group by datepart(mm,缴费日期) 
      

  13.   


    create table [#tb]([单据号码] varchar(6),[缴费金额] numeric(5,2),[缴费日期] datetime)
    insert [#tb]
    select '000001',168.00,'2010-01-12' union all
    select '000002',168.00,'2010-01-13' union all
    select '000003',168.00,'2010-01-14' union all
    select '000004',168.00,'2010-02-12' union all
    select '000005',168.00,'2010-03-12' union all
    select '000006',168.00,'2010-04-12' union all
    select '000007',168.00,'2010-03-12' union all
    select '000008',168.00,'2010-03-12' union all
    select '000009',168.00,'2010-03-12' union all
    select '000012',168.00,'2010-03-12' union all
    select '000013',168.00,'2010-03-12' union all
    select '000014',168.00,'2010-03-12' union all
    select '000015',168.00,'2010-04-12' union all
    select '000023',168.00,'2010-09-12' union all
    select '000033',100.00,'2010-04-12' union all
    select '000034',200.00,'2010-03-12' union all
    select '000035',200.00,'2010-03-12'
    ---step 1 insert 临时表
    select *,identity(int,1,1)as id,0 as type into #ta from #tb ---按照连续单据号这个规则来更新临时表
    declare @num int
    set @num =0
    update #ta set type = @num ,
                   @num = (case when cast(a.单据号码 as int) <> (select cast(单据号码 as int)+1 from #ta where id = a.id-1) then @num+1 else @num end)
                   from #ta a---创建查询
    select isnull(a.单据起始号,'') as 单据起始号,isnull(a.单据结束号,'')as 单据结束号,isnull(ltrim(a.单据数量),'') as 单据数量,b.开具金额,ltrim(b.开具月份)+'月' as 开具月份 
    from
    (select  type, min(单据号码) as 单据起始号,
    max(单据号码) as 单据结束号,count(*) as 单据数量   from #ta  group by type) a 
    right join 
    (select sum(缴费金额) as 开具金额,  type ,month(缴费日期)as 开具月份 ,min(id) as id
    from #ta group by type,month(缴费日期) ) 
    b on a.type = b.type and b.id =(select min(id) from #ta where type = b.type) order by b.type , b.开具月份--释放临时表 drop table #ta
    drop table #tb