利用存储过程实现交叉表格式数据查询的一种通用方法

问题描述:如何生成以下表结构的交叉报表格式的数据查询。  

CREATE TABLE [dbo].[testTable] (

       [id] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,

       [dDate] [datetime] NOT NULL ,

       [dTime] [int] NOT NULL ,

       [value] [decimal](18, 4) NULL 

) ON [PRIMARY]

GO 

ALTER TABLE [dbo].[testTable] ADD

       CONSTRAINT [PK_testTable] PRIMARY KEY  CLUSTERED

       (

              [id],

              [dDate],

              [dTime]

       )  ON [PRIMARY]

GO 

数据如下表所示:

Id

dDate

dTime

value

压力1

<?xml:namespace prefix = st1 />2005-1-1

8

15.23

压力1

2005-1-1

9

14.26

压力1

2005-1-1

10

18.78

压力1

2005-1-1

11

20.12

压力1

2005-1-1

12

30.25

压力2

2005-1-1

8

18.23

压力2

2005-1-1

9

19.26

压力2

2005-1-1

10

14.78

压力2

2005-1-1

11

22.12

压力2

2005-1-1

12

20.25

压力3

2005-1-1

8

16.23

压力3

2005-1-1

9

29.26

压力3

2005-1-1

10

24.78

压力3

2005-1-1

11

25.12

压力3

2005-1-1

12

24.25

表一 

生成的报表格式如下: 

日期

时间

压力1

压力2

压力3

2005-1-1

8

15.23

18.23

16.23

2005-1-1

9

14.26

19.26

29.26

2005-1-1

10

18.78

14.78

24.78

2005-1-1

11

20.12

22.12

25.12

2005-1-1

12

30.25

20.25

24.25

表二 

表格经过转换(转换为交叉表格式),压缩了重复的数据,而且也便于查看和比较数据间的关系。 

实现原理:

1.生成时间临时表,格式如下表: 

日期

时间

2005-1-1

8

2005-1-1

9

2005-1-1

10

2005-1-1

11

2005-1-1

12

表三 

2.再生成以下临时表,格式如下表: 

日期

时间

压力1

2005-1-1

8

15.23

2005-1-1

9

14.26

2005-1-1

10

18.78

2005-1-1

11

20.12

2005-1-1

12

30.25

表四 

日期

时间

压力2

2005-1-1

8

18.23

2005-1-1

9

19.26

2005-1-1

10

14.78

2005-1-1

11

22.12

2005-1-1

12

20.25

表五 

日期

时间

压力3

2005-1-1

8

16.23

2005-1-1

9

29.26

2005-1-1

10

24.78

2005-1-1

11

25.12

2005-1-1

12

24.25

表六 

3.然后使用SQL语句把它们连接起来,形成表二格式。

4.为了使得存储过程具有极大的灵活性,能够适应不同的表名称、不同的列名称、查询不同的列和查询不同的时间,应当使用动态SQL语句编写存储过程。

 

存储过程语句如下: 

None.gif CREATE     PROCEDURE pSearchData
None.gif    @tableName varchar(
100 ),@columnFieldName varchar( 100 ),@dateFieldName varchar( 100 ),@timeFieldName varchar( 100 ),@valueFieldName varchar( 100 ),
None.gif    @searchColumn varchar(
1000 ),@SearchTime varchar( 1000 )
None.gif
-- @tableName 为查询表名,@columnFieldName 为查询列字段名,@dateFieldName 为查询日期字段名,@timeFieldName 为查询时间字段名,@valueFieldName 为查询值字段名
None.gif
-- @searchColumn 为要查询的列的字符串,@SearchTime 为要查询的时间字符串
None.gifAS
None.gifdeclare @i 
int ,@j  int ,@dTime  int ,@timeRowNum  int ,@colID  int
None.gifdeclare @dDate datetime
None.gifdeclare @sql varchar(
4000 ),@sqlTableName varchar( 1000 ),@sqlJoinSelect varchar( 4000 ),@sqlJoinFrom varchar( 4000 )
None.gif
None.gif
set  @i  =  dbo.fGetParamTotal(@searchColumn)
None.gif
set  @timeRowNum  =  dbo.fGetParamTotal(@SearchTime)
None.gif
set  @sql  =   ''
None.gif
set  @sqlJoinSelect  =   ' select Convert(varchar(2),#tempTime.dTime) + '' :00 '' as 时间 '
None.gif
set  @sqlJoinFrom  =   '  from #tempTime  '
None.gif
set  @colID  =   1
None.gif
None.gif
--  建立临时时间表,并插入数据
None.gifCREATE TABLE [dbo].[#tempTime] ([dDate] [datetime] NOT NULL ,[dTime] [
int ] NOT NULL ) ON [PRIMARY]
None.gif
while  (@timeRowNum  > 0 )
None.gifbegin 
None.gif
None.gif    
set  @dDate  =  Convert(datetime,dbo.fGetParamValue(@SearchTime,@timeRowNum))
None.gif    
set  @dDate  =  Convert(datetime,dbo.fToDate(@dDate))
None.gif    
set  @dTime  =  datepart(hour,Convert(datetime,dbo.fGetParamValue(@SearchTime,@timeRowNum)))
None.gif    
None.gif    INSERT INTO #tempTime(dDate, dTime) VALUES (@dDate, @dTime)
None.gif    
set  @timeRowNum  =  @timeRowNum  -   1
None.gifend
None.gif
-- 建立动态sql语句生成临时表,并且连接临时表
None.gif
if  @i  <>   0
None.gifbegin
None.gif    
while  (@i  >   0 )
None.gif    begin 
None.gif        
set  @sqlTableName  =   ' #tempValue ' +   Convert(varchar( 2 ),@colID)
None.gif        
set  @sql  =  @sql  +  N ' select  ' +  @columnFieldName  +  N ' , ' + @dateFieldName  + N ' , ' + @timeFieldName + N ' , ' + @valueFieldName  + N '  into  '   +  @sqlTableName  +  N '  
None.gif
                 from  ' +@tableName+N '  where  ' + @columnFieldName + N '   =   ''' + Convert(varchar(1000),dbo.fGetParamValue(@searchColumn,@colID)) +N ''''
None.gif

None.gif        
-- 求第一个查询日期和时间
None.gif        
set  @dDate  =  Convert(datetime,dbo.fGetParamValue(@SearchTime, 1 ))
None.gif        
set  @dDate  =  Convert(datetime,dbo.fToDate(@dDate))
None.gif        
set  @dTime  =  datepart(hour,Convert(datetime,dbo.fGetParamValue(@SearchTime, 1 )))
None.gif
None.gif        
set  @sql  =  @sql  +  N '  and ((( '   +  @dateFieldName  +  N '  =  '''   +  Convert(varchar( 100 ),@dDate, 121 +  N ''' ) and ( ' +  @timeFieldName  +  N '  =  ' +  Convert(varchar( 100 ),@dTime)  +  N ' )) '
None.gif        
set  @j  =   2
None.gif        
while  (@j  <=  dbo.fGetParamTotal(@SearchTime))
None.gif        begin
None.gif            
set  @dDate  =  Convert(datetime,dbo.fGetParamValue(@SearchTime,@j))
None.gif            
set  @dDate  =  Convert(datetime,dbo.fToDate(@dDate))
None.gif            
set  @dTime  =  datepart(hour,Convert(datetime,dbo.fGetParamValue(@SearchTime,@j)))
None.gif
None.gif            
set  @sql  =  @sql  +  N '  or (( '   +  @dateFieldName  +  N '  =  '''   +  Convert(varchar( 100 ),@dDate, 121 +  N ''' ) and ( ' +  @timeFieldName  +  N '  =  ' +  Convert(varchar( 100 ),@dTime)  +  N ' )) '
None.gif            
set  @j  =  @j  + 1
None.gif        end        
None.gif        
set  @sql  =  @sql  +  N ' ) '
None.gif
None.gif        
set  @sqlJoinSelect  =  @sqlJoinSelect  +   N ' , ' + @sqlTableName  + N ' . ' + @valueFieldName + N '  as  '   +  Convert(varchar( 1000 ),dbo.fGetParamValue(@searchColumn,@colID))
None.gif        
set  @sqlJoinFrom  =  @sqlJoinFrom  +  N '  left join  ' +  @sqlTableName  +  N '  on #tempTime.dDate =  ' +  @sqlTableName  +  N ' . ' + @dateFieldName  +  N '  and #tempTime.dTime =  ' +  @sqlTableName  +  N ' . ' + @timeFieldName
None.gif
None.gif        
set  @i  =  @i  -   1
None.gif        
set  @colID  =  @colID  + 1
None.gif    end
None.gif
None.gifexec(@sql 
+  @sqlJoinSelect  +  @sqlJoinFrom  + '  order by #tempTime.dDate,#tempTime.dTime ' )
None.gif
-- print @sql  +  @sqlJoinSelect  +  @sqlJoinFrom  + '  order by #tempTime.dDate,#tempTime.dTime '
None.gif
None.gifend                                
None.gif
None.gifGO

其中使用三个函数,代码分别如下:
函数一:

None.gif CREATE  FUNCTION fGetParamTotal
None.gif(@param varchar(
1000 ))
None.gifRETURNS 
int
None.gifAS
None.gif
None.gifBEGIN
None.gif
None.gifdeclare @ParamTotal 
int
None.gif
set  @ParamTotal  =   0
None.gif
if  @param  =   ''
None.gif    
return   0
None.gif
None.gif    
while  (charindex( ' , ' ,@param)  <>   0 )
None.gif    begin
None.gif        
set  @ParamTotal  =  @ParamTotal  +   1
None.gif        
set  @param  =  substring(@param,charindex( ' , ' ,@param) + 1 ,len(@param))
None.gif    end
None.gif
return  @ParamTotal  +   1
None.gif
None.gifEND

函数二:

None.gif CREATE  FUNCTION fGetParamValue
None.gif(@param varchar(
1000 ),@id  int )
None.gifRETURNS varchar(
1000 )
None.gifAS
None.gif
None.gifBEGIN
None.gif
None.gifdeclare @ParamTotal 
int
None.gifdeclare @i 
int
None.gifdeclare @subString varchar(
1000 )
None.gif
set  @ParamTotal  =  dbo.fGetParamTotal(@param)
None.gif
set  @subString  =   ''
None.gif
set  @i  =   1
None.gif
if  @id  <=   0  
None.gif    
return  @subString
None.gif
if  @ParamTotal  >=  @id    
None.gifbegin
None.gif    
while  (@id  >  @i)
None.gif    begin
None.gif
--           set  @ParamTotal  =  @ParamTotal  +   1
None.gif        
set  @param  =  substring(@param,charindex( ' , ' ,@param) + 1 ,len(@param))
None.gif        
set  @i  =  @i  +   1
None.gif    end
None.gif        
if  (charindex( ' , ' ,@param)  =   0 )
None.gif            
set  @subString  =  @param
None.gif    
else
None.gif         
set  @subString  =  substring(@param, 1 ,charindex( ' , ' ,@param)  -   1 )
None.gifend
None.gif
return  @subString
None.gifEND

函数三:

None.gif CREATE  FUNCTION fToDate(@DateTime datetime)
None.gifRETURNS varchar(
10
None.gifAS
None.gifbegin
None.gifdeclare @Date varchar(
10 )
None.gif
None.gif
set  @Date  =  convert( char ( 4 ),year(@DateTime))  +   ' - '   +  convert(varchar( 2 ),month(@DateTime))  +   ' - '   +  convert(varchar( 2 ),day(@DateTime))
None.gif
None.gif
return  @Date
None.gifend

存储过程的参数@searchColumn 为要查询的列的字符串,@SearchTime 为要查询的时间字符串,字符串中用逗号分割数据。

执行存储过程的语句如下所示:

pSearchData 'testTable','id','dDate','dTime','value','压力1, 压力2, 压力3','2005-1-1 8:00:00,2005-1-1 9:00:00,2005-1-1 12:00:00'

转载于:https://www.cnblogs.com/pcbhyy/archive/2005/09/09/233362.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值