我在下面的分公司工作,我们统一使用的报表系统功能完全不够强大,除了看看各地市分公司的总收入之外,完全不能满足分公司每个月个性化的经营分析。于是总公司开放出数据库,让我们具有访问权限,可随便取数据,好让我们自己取出数据来做分析。可这样一来我就麻烦了,主任,领导每月每次都装B似的感觉是个经营分析的能手,比如先让我将数据按照设备类别-渠道进行汇总成一长表,然后本月和上月环比一看,对比不明显,虽然本月总收入下降,但是汇总后的数据也没有看出具体哪块下降的厉害,于是再具体细分,再按费用来分,好,刚才汇总出一张 渠道-设备类别的汇总表,那么费用项一共又具有8种,于是,刚才的汇总表再按费用项细分又得到8张表,OK,8张愚蠢的表出来给主任一看,还是看不出个名堂,不知道收入下降在哪,于是得到命令,再按营业区划分,我们营业区有4个,于是4×8=32 ...........每个月我就要被这样的事情给玩死,三年以来我不知道写了至少上万条的SQL命令。虽然某些固定的报表,数据等等,我都编写了存储过程,还用JSP建立了一个本地报表
数据查询系统,解决了不少业务上的问题。但是每个月的经营分析我最头痛,我几乎成了个专写SQL的机器,不停的根据傻B领导的要求写SQL。
所以现在特来发帖求助,不知道有什么好办法能够写一些智能一点的存储过程之类的,让每个月的收入和上月的对比,运行一下,就得到结果汇总表,能看出下降点最大的地方在哪。比如,每月都有一今年5月收入明细表:sr200905 ,这里的号码字段是主键,
字段如下:
号码   功能费   信息费   长途费   合计   客户群  设备类别  营业区
2223      2.00    3.00     5.00   10.00   大客户    固话     苏州
2347      1.00    3.00     4.00   8.00    家庭客户  手机     杭州
2346      1.00    3.00     4.00   8.00    商业客户  手机     杭州
.........
一张表几万条记录吧
让他和今年4月的收入明细表 sr200904 来进行汇总对比,能很快的看出5月的收入和四月比到底下降在哪个客户群,如果具体到某个客户群后,再细分到设备类别,看哪个设备类别的收入下降最厉害。其实我也知道,这鬼分析是不可能真正起什么作用的,不过是能给领导在开会的时候把收入下降点给说明清楚而已。我希望大家有办法能帮个忙,说说自己的思路,让我摆脱这苦海,让我有时间学习新的东西。有说的在点上的,分不够我再重新开帖送分哦!

解决方案 »

  1.   

    感觉困扰楼主的问题基本上可以通过动态SQL来解决;大致是将访问的表名以动态的日期数据后缀方式构造成一段或者多段动态SQL。
      

  2.   

    举个简单的例子:declare @sql varchar(8000)--读取本月表
    set @sql='select * from sr'+convert(char(6),getdate(),112)
    print @sql
    --select * from sr200906
    --读取上月表
    set @sql='select * from sr'+convert(char(6),dateadd(mm,-1,getdate()),112)
    print @sql
    --select * from sr200905
      

  3.   

    动态sql语句基本语法 
    1 :普通SQL语句可以用Exec执行 eg:   Select * from tableName 
             Exec('select * from tableName') 
             Exec sp_executesql N'select * from tableName'    -- 请注意字符串前一定要加N 2:字段名,表名,数据库名之类作为变量时,必须用动态SQL eg:   
    declare @fname varchar(20) 
    set @fname = 'FiledName' 
    Select @fname from tableName              -- 错误,不会提示错误,但结果为固定值FiledName,并非所要。 
    Exec('select ' + @fname + ' from tableName')     -- 请注意 加号前后的 单引号的边上加空格 当然将字符串改成变量的形式也可 
    declare @fname varchar(20) 
    set @fname = 'FiledName' --设置字段名 declare @s varchar(1000) 
    set @s = 'select ' + @fname + ' from tableName' 
    Exec(@s)                -- 成功 
    exec sp_executesql @s   -- 此句会报错 declare @s Nvarchar(1000)  -- 注意此处改为nvarchar(1000) 
    set @s = 'select ' + @fname + ' from tableName' 
    Exec(@s)                -- 成功     
    exec sp_executesql @s   -- 此句正确 3. 输出参数 
    declare @num int, 
            @sqls nvarchar(4000) 
    set @sqls='select count(*) from tableName' 
    exec(@sqls) 
    --如何将exec执行结果放入变量中? declare @num int, 
                   @sqls nvarchar(4000) 
    set @sqls='select @a=count(*) from tableName ' 
    exec sp_executesql @sqls,N'@a int output',@num output 
    select @num 几个是几个相关实例:--1. 使用 EXEC 实现的动态参数存储过程
    CREATE PROC p_test
    @para1 varchar(10)=null,
    @para2 varchar(10)=null,
    @para3 varchar(10)=null,
    @para4 varchar(10)=null
    AS
    SET NOCOUNT ON
    DECLARE @sql varchar(8000)
    SET @sql='SELECT * FROM tbname WHERE 1=1'
    IF @para1 IS NOT NULL
        SET @sql=@sql+' AND col1='''+@para1+''''
    IF @para2 IS NOT NULL
        SET @sql=@sql+' AND col2='''+@para2+''''
    IF @para3 IS NOT NULL
        SET @sql=@sql+' AND col3='''+@para3+''''
    IF @para4 IS NOT NULL
        SET @sql=@sql+' AND col4='''+@para4+''''
    EXEC(@sql)
    GO
    /*======================================================*/--2. 使用 sp_executesql 实现的动态参数存储过程
    CREATE PROC p_test
    @para1 varchar(10)=null,
    @para2 datetime=null,
    @para3 varchar(10)=null,
    @para4 int=null
    AS
    SET NOCOUNT ON
    DECLARE @sql nvarchar(4000)
    SET @sql='SELECT * FROM tbname WHERE 1=1'
        +CASE WHEN @para1 IS NULL THEN '' ELSE ' AND col1=@para1' END
        +CASE WHEN @para2 IS NULL THEN '' ELSE ' AND col2=@para2' END
        +CASE WHEN @para3 IS NULL THEN '' ELSE ' AND col3=@para3' END
        +CASE WHEN @para4 IS NULL THEN '' ELSE ' AND col4=@para4' END
    EXEC sp_executesql @sql,N'
        @para1 varchar(10)=null,
        @para2 datetime=null,
        @para3 varchar(10)=null,
        @para4 int=null
    ',@para1,@para2,@para3,@para4
    GO
    /*======================================================*/--3. 不使用动态 Transact-SQL 语句实现的动态参数存储过程
    CREATE PROC p_test
    @para1 varchar(10)=null,
    @para2 datetime=null,
    @para3 varchar(10)=null,
    @para4 int=null
    AS
    SET NOCOUNT ON
    SELECT * FROM tbname 
    WHERE (@para1 IS NULL OR col1=@para1)
        AND (@para2 IS NULL OR col2=@para2)
        AND (@para3 IS NULL OR col3=@para3)
        AND (@para4 IS NULL OR col4=@para4)支持1楼的分析,以上供楼主参考.
      

  4.   

    恩,感谢。不过,我想得到的动态分析的sql 不是因为表名作为变量的问题。而是,比如先头一道分析,得出环比结果:
     
    select 营业区,(a.合计-b.合计) as 环比 from 
    (select 营业区,sum(合计) as 合计 from sr200905 group by 营业区) as a 
    join 
    (select 营业区,sum(合计) as 合计 from sr200904 group by 营业区) as b
    on a.营业区=b.营业区 order by 环比 
    运行后,比如得到营业区='杭州' 的收入下降最厉害,那么然后我再对营业区='杭州' 的收入,按照设备类别来分析: 
    select 设备类别,(a.合计-b.合计) as 环比 from 
    (select 设备类别,sum(合计) as 合计 from sr200905 where 营业区='杭州' group by 设备类别) as a 
    join 
    (select 设备类别,sum(合计) as 合计 from sr200904 where 营业区='杭州' group by 设备类别) as b
    on a.设备类别=b.设备类别 order by 环比 
    这样又得到在营业区='杭州' 时候,设备类别 的值为'手机' 的收入下降最大,然后又根据现有的条件,继续往下分。所以现在的问题在于,我得到 营业区='杭州' 和之后设备类别 的值为'手机' 为收入下降点的结果,是运行以上所示的命令人工判断的。我的目的是想可不可以动态判断我我如上所示的结果,也就是动态的细分出,收入下降点。  
      

  5.   

    应该行吧?
    declare @a varchar(10)
    select top 1 @a=a.营业区  from 
    (select 营业区,sum(合计) as 合计 from sr200905 group by 营业区) as a 
    join 
    (select 营业区,sum(合计) as 合计 from sr200904 group by 营业区) as b
    on a.营业区=b.营业区 order by a.营业区
    select a.营业区,a.设备类别,(a.合计-b.合计) as 环比 from 
    (select 营业区,设备类别,sum(合计) as 合计 from sr200905 where 营业区=@a group by 设备类别,营业区) as a 
    join 
    (select 设备类别,sum(合计) as 合计 from sr200904 where 营业区=@a group by 设备类别) as b
    on a.设备类别=b.设备类别 order by 环比