设为首页 加入收藏

TOP

[MSSQL]采用pivot函数实现动态行转列(一)
2015-07-24 12:05:52 来源: 作者: 【 】 浏览:90
Tags:MSSQL 采用 pivot 函数 实现 动态

环境要求:2005+

在日常需求中经常会有行转列的事情需求处理,如果不是动态的行,那么我们可以采取case when 罗列处理。

在sql 2005以前处理动态行或列的时候,通常采用拼接字符串的方法处理,在2005以后新增了pivot函数之后,我可以利用这样函数来处理。

1.动态SQL注入式判断函数

--既然是用到了动态SQL,就有一个老话题:SQL注入。建一个注入性字符的判断函数。
CREATE FUNCTION [dbo].[fn_CheckSQLInjection]
(
 @Col nvarchar(4000)
)
RETURNS BIT --如果存在可能的注入字符返回true,反之返回false
AS
BEGIN
DECLARE @result bit;
  IF  
     UPPER(@Col) LIKE UPPER(N'%0x%')
  OR UPPER(@Col) LIKE UPPER(N'%;%')
  OR UPPER(@Col) LIKE UPPER(N'%''%')
  OR UPPER(@Col) LIKE UPPER(N'%--%')
  OR UPPER(@Col) LIKE UPPER(N'%/*%*/%')
  OR UPPER(@Col) LIKE UPPER(N'%EXEC%')
  OR UPPER(@Col) LIKE UPPER(N'%xp_%')
  OR UPPER(@Col) LIKE UPPER(N'%sp_%')
  OR UPPER(@Col) LIKE UPPER(N'%SELECT%')
  OR UPPER(@Col) LIKE UPPER(N'%INSERT%')
  OR UPPER(@Col) LIKE UPPER(N'%UPDATE%')
  OR UPPER(@Col) LIKE UPPER(N'%DELETE%')
  OR UPPER(@Col) LIKE UPPER(N'%TRUNCATE%')
  OR UPPER(@Col) LIKE UPPER(N'%CREATE%')
  OR UPPER(@Col) LIKE UPPER(N'%ALTER%')
  OR UPPER(@Col) LIKE UPPER(N'%DROP%')
  SET @result=1
 ELSE
  SET @result=0
 return @result
END
GO

2.需求:

--通过日期查询几个表联合,按照检验项目分类,按日期横向展示

select a.检验项目 , CONVERT(char(10),a.日期,120)日期,Convert(decimal(18,2),cast((SUM(a.测试数量)-SUM(a.不良数量)) as decimal(18,2))/sum(测试数量))*100  as 良率 
--into  #tempcob
from (select 日期,检验项目, 测试数量, 不良数量 from 制程COB成测 union all 
select 日期,检验项目, 测试数量, 不良数量 from 制程COB外观 union all 
             select 日期,检验项目,测试数量, 不良数量 from 制程COB绑测 union all 
select 送检日期,'FQC_COB_检验',检验数量,不合格数量 from 制程FQC_COB_检验 
  ) as a 
  where CONVERT(char(10),日期,120)>='2014-10-01'  and CONVERT(char(10),日期,120)<= '2014-10-30'
 group by a.检验项目,a.日期

3.解决方案:

--抓取数据写入临时表#tempcob
select a.检验项目 , CONVERT(char(10),a.日期,120)日期,Convert(decimal(18,2),cast((SUM(a.测试数量)-SUM(a.不良数量)) as decimal(18,2))/sum(测试数量))*100  as 良率 
into  #tempcob
from (select 日期,检验项目, 测试数量, 不良数量 from 制程COB成测 union all 
select 日期,检验项目, 测试数量, 不良数量 from 制程COB外观 union all 
             select 日期,检验项目,测试数量, 不良数量 from 制程COB绑测 union all 
select 送检日期,'FQC_COB_检验',检验数量,不合格数量 from 制程FQC_COB_检验 
  ) as a 
  where CONVERT(char(10),日期,120)>='2014-10-01'  and CONVERT(char(10),日期,120)<= '2014-10-30'
 group by a.检验项目,a.日期 
 
--查看临时表数据,取分布日期(不重复)
--select   日期 from #tempcob
--select  distinct 日期 from #tempcob
DECLARE @SQL NVARCHAR(4000)=N'';
--这里使用了xml处理来处理类组字符串
SET @SQL=STUFF((SELECT N','+QUOTENAME(b.日期) FROM (select  distinct 日期 from #tempcob) as b
 FOR XML PATH('')),1,1,N''); 
--加入了xml处理和SQL注入预防判断
IF  dbo.fn_CheckSQLInjection(@SQL)=0 
SET @SQL='select * from #tempcob pivot (max(良率) for 日期 in ('+@SQL+')) as tt'
EXEC(@SQL);
drop table #tempcob


4.结果:

\vcEOJnXa/oBHTQ54lN1xlO6n1PDa3Vc3J+s1jj27Pht3o41jX+n/RZn4jCy3lCgfuQNAamAd944SQtDLpzLFoeqk8V67Lk75u2krH1Q7kZ/WvPLgrG5rv07leP90HoN87R+wVeEdls8lZzOzNvXN07p5yNhSdfBW5lpAmmrQ7+xXoPSiO9Kk4E915pEs39XvGr45hX4uqMJEaXrAfKXkhedWZFFJyzERVZyLVf0wMVnKpzLFscgJ9rFXpLGL1J8meMLXpYzMMLHTEtmAlWcGZshP932v1v4CjvpxfcSa09F31y1k/SX4+PHs/2mr3cSNVZxLpq1kcg30YdhVnUut5rGlD52iNO3Wbxx6LPTtApegJXWteul6Z5MZxoI+hj+tgKJKel2XCuhye18hD15xlWffz+PfVLs3HR61r7Cy4Tj9qzasNoJIlC1fVT2ce8Tle5NgocC0pTUPtV/C5U88jbhpZeSbqZ6d2ruk9LWLi+ie5joiEKsNEMjLJfqT0BeSVZ1JAx3GTVJ2JXP/Dd35ymQX6vXEbQEp/BPvXr1Lw/iQaH47YoVSdiYT5KPKqMwnZyWeHv20ilFVnopYB0Wc7n6f/SFO/j0kHuHfUFijxBuPHNaesvJ3o/QrqOo8VOk23P6nTPHaS9jzutX79v4UGc8Rz6qF66MgmFv3j10P60z+ZE69nHAA6gRR2M5t05ujmddObOE8fyqPPj/pUzUExiv8ofWfxPJj4rQomYOIT8CWwEzDxCfgS2AmY+AR8CewETHwCvgR2AiY+AV8COzk5Jr/+2y5974Pv0LNnz+jChQvphba3t+nKlStpfPRTdJp0egHzsG+OuiYmbB7yedyEzTGU3mhj0phyjFzH9Tku52GTzhxNOSaOIwiAAAiAAAiAAAiAAAiAAAiAAAjUmUCpHQ7mAd8c8xqKp+HhvDz6XF5afo6HQ2WOOh/KAxkIgAAIgAAIgAAIgAAIgAAIgAAIzCqBUm4aOauwoRcIgAAIgAAIgAAIgAAIgAAIgAAI1IXAvH6vZZqfaV9/mrqX4drg77cCmICJT8CXwE7AxCfgS2AnYOIT8CWwEzDxCfgS2AmY+AR8CewETHwCvmSSdjL/3vBrvwYTlHzjG9+gr776inCcDocJNj

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Oracle用户管理(一) 下一篇查询Oracle数据库中带有lob字段的..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: