sql server 纵向表横向输出的实现

有时候,我们经常需要通过纵向存储的数据,在做报表的时候,横向输出显示出来。

最典型的例子:

问卷系统中的存储答案的表,存储的数据类似于(存储形式):

 

c_UserId (用户编号) c_QuestionId(问题编号) c_Item(答案)

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

1 1 A

 

1 2 B

1 3 C

1 4 D

 

2 1 D

 

2 2 D

3 A

4 B

以上表中存储了俩个用户的答题信息。

但是我们可能需要在做报表的时候,需要输出类似于这样的信息(输出形式):

c_UserId (用户编号)   Q1(问题编号1) Q2(问题编号2) Q3(问题编号3) Q4(问题编号4)

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

1 A B C D

2 D D A B

 

我们需要借组 sql server2005 中的pivot 函数+聚合函数来实现,但是,这个函数,个人感觉还是不是太灵活(呵呵 ,本人有点菜),所以,写了一个存储过程来对这个pivot 函数的转换列进行了封装。调用起来很方便,自动获取纵向表中相同行的最大值,不会当心遗漏某些行。

 

 



 

下面是源码(在这个存储过程中,使用了中间表,估计会有效率问题,希望大虾们不吝赐教):

 

 

/**

* 翻转表(纵向表横向输出)

*/

if exists(select * from sysobjects where name='Proc_Pivot_Table')

drop proc Proc_Pivot_Table

go

create proc Proc_Pivot_Table

   @Table varchar(50) --表名

  ,@ColumName varchar(50) --要横向显示的字段名 答案

  ,@ColumKeyItem varchar(50) --要横向显示的字段名的Key字段名 问题编号

  ,@KeyColumItem varchar(50) --横向显示的Key字段名 用户编号

  ,@ColumAsName varchar(50)=null --key指定别名(要横向显示的字段列名称)

as

begin

--设置要横向显示的字段列名称,如果没有设置,则默认取“要横向显示的字段名”作为列名称

if (@ColumAsName is null) set @ColumAsName=@ColumName

declare @MaxColums int

exec('if exists( select * from sysobjects where name=''temp_T1'') 

drop table temp_T1 ')

exec (' select top 1 count(Convert(varchar(max),'+@ColumName+')) as c_ItemsNum 

 INTO temp_T1  from '+@Table+'  group by '+@KeyColumItem+' order by c_ItemsNum desc')

 

select @MaxColums=c_ItemsNum from temp_T1

   print @MaxColums

 

declare @i int,@SQL varchar(8000),@filds varchar(8000)

set @i=1

        --拼接sql

set @SQL='SELECT '+@KeyColumItem+' '

        --开始拼接查询字段

set @filds=''

while(@i<=@MaxColums)

begin

set @filds=@filds+' , ['+Convert(varchar(5),@i)+']'

set @SQL=@SQL+' , max(['+Convert(varchar(5),@i)+']) as '+@ColumAsName+Convert(varchar(5),@i)+' '

set @i=@i+1

end

        --开始转置

set @SQL=@SQL+' from '+@Table+' pivot (max('+@ColumName+')for '+@ColumKeyItem+' in

                       ( [0] '+@filds+')) as pvt Group by '+@KeyColumItem

print @SQL

exec(@SQL)

end

go

 

 



 

下面是测试用例

 

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

/**

* 构造用利

*/

if exists(select * from sysobjects where name='T_Answer_Test')

drop table T_Answer_Test

go

create table T_Answer_Test(

c_Id int identity(1,1) not null, --序号

c_UserId int, --用户编号

c_QuestionId int, --问题编号

c_Item nvarchar(max) --答案

)

go

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','1','A')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','2','A')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','3','B')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','4','C')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','5','D')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('1','6','A')

 

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('2','1','D')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('2','2','')

 

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','1','A')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','2','B')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','3','')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','4','D')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','5','D')

insert into T_Answer_Test(c_UserId,c_QuestionId,c_Item) values('3','6','')

 

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

/**

* 测试

*/

DECLARE 

   @Table varchar(50) --表名

  ,@ColumName varchar(50) --要横向显示的字段名 答案

  ,@ColumKeyItem varchar(50) --要横向显示的字段名的Key字段名 问题编号

  ,@KeyColumItem varchar(50) --横向显示的Key字段名 用户编号

  ,@ColumAsName varchar(50) --key指定别名

set @Table='T_Answer_Test'--答案表名称

set @ColumName='c_Item'--选项

set @KeyColumItem='c_UserId'--用户编号

set @ColumKeyItem='c_QuestionId'--问题编号

set @ColumAsName='Q'--问题别名

--显示原始数据

select c_UserId,c_QuestionId,c_Item from T_Answer_Test

--横向输出数据

exec Proc_Pivot_Table @Table,@ColumName,@ColumKeyItem,@KeyColumItem,@ColumAsName

 

 


这里晒出来sql源码:

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【赛迪网-IT技术报道】SQL Server数据库查询速度慢的原因有很多,常见的有以下几种:   1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)     2、I/O吞吐量小,形成了瓶颈效应。     3、没有创建计算列导致查询不优化。     4、内存不足     5、网络速度慢     6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)     7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)     8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。     9、返回了不必要的行和列     10、查询语句不好,没有优化 ●可以通过以下方法来优化查询 : 1、把数据、日志、索引放到不同的I/O设备上,增加读取速度,以前可以将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提高I/O越重要。 2、纵向横向分割,减少的尺寸(sp_spaceuse) 3、升级硬件 4、根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。索引应该尽量小,使用字节数小的列建索引好(参照索引的创建),不要对有限的几个值的字段建单一索引如性别字段。 5、提高网速。 6、扩大服务器的内存,Windows 2000和SQL server 2000能支持4-8G的内存。 配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。运行 Microsoft SQL Server? 2000时,可考虑将虚拟内存大小设置为计算机中安装的物理内存的1.5倍。如果另外安装了全文检索功能,并打算运行Microsoft搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置为至少是计算机中安装的物理内存的3倍。将SQL Server max server memory服务器配置选项配置为物理内存的1.5倍(虚拟内存大小设置的一半)。 7、增加服务器CPU个数;但是必须 明白并行处理串行处理更需要资源例如内存。使用并行还是串行程是MsSQL自动评估选择的。单个任务分解成多个任务,就可以在处理器上运行。例如耽搁查询 的排序、连接、扫描和GROUP BY字句同时执行,SQL SERVER根据系统的负载情况决定最优的并行等级,复杂的需要消耗大量的CPU的查询最适合并行处理。但是更新操作UPDATE,INSERT, DELETE还不能并行处理。 8、如果是使用like进行查询的话,简单的使用index是不行的,但是全文索引,耗空间。 like ''a%'' 使用索引 like ''%a'' 不使用索引用 like ''%a%'' 查询时,查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于字段的值很长的建全文索引。 9、DB Server 和APPLication Server 分离;OLTP和OLAP分离 10、分布式分区视图可用于实现数据库服务器联合体。 联合体是一组分开管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服务器联合体的机制能够扩大一组服务器,以支持大型的多层 Web 站点的处理需要。有关更多信息,参见设计联合数据库服务器。(参照SQL帮助文件''分区视图'') a、在实现分区视图之前,必须先水平分区 b、 在创建成员后,在每个成员服务器上定义一个分布式分区视图,并且每个视图具有相同的名称。这样,引用分布式分区视图名的查询可以在任何一个成员服务器上 运行。系统操作如同每个成员服务器上都有一个原始的复本一样,但其实每个服务器上只有一个成员和一个分布式分区视图。数据的位置对应用程序是透明的。 11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收缩数据和日志 DBCC SHRINKDB,DBCC SHRINKFILE. 设置自动收缩日志.对于大的数据库不要设置数据库自动增长,它会降低服务器的性能。 在T-sql的写法上有很大的讲究,下面列出常见的要点:首先,DBMS处理查询计划的过程是这样的:   1、 查询语句的词法、语法检查     2、 将语句提交给DBMS的查询优化器     3、 优化器做代数优化和存取路径的优化     4、 由预编译模块生成查询规划     5、 然后在合适的时间提交给系统处理执行     6、 最后将执行结果返回给用户。 其次,看一下SQL SERVER的数据存放的结构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。
【论文关键词】SQLserver 数据库 安全监控系统 【论文摘要】数据库监控信息获取策略的研究内容包括:数据库威胁来源、威胁特征、 数据库审计事件、数据库运行性能指标等。通过对数据库所受威胁的研究,建立数据库 威胁知识库,可以了解数据库攻击手段、攻击特征、检测信息源,进而制定监控信息获 取策略,保证数据库监控信息获取的完备性与可靠性。本文探讨了SQL?Server数据库安 全监控系统的实现。      一、系统整体结构   下面本文将分别从横向纵向以及切向对数据库安全监控系统进行了结构上的再设 计,改善了原有系统结构设计上的不足之处,并对其不同的划分结果进行分析。   1、横向结构   从横向看,该系统按照信息获取系统、分析机系统、控制台系统按照功能不同进行 了重新的系统模块结构的划分,并补充了实时状态查询模块,增加了数据库安全监控系 统安全威胁分析的数据来源,其横向结构如图1所示:   a)信息获取子系统   b)分析机子系统   c)控制台子系统   其中信息获取子系统位于整个系统的底层,是系统运行的基础所在。它采用主机获 取的方式,对数据库服务器进行实时的数据信息获取,获取主机以及网络通讯会话轨迹 ,并对获取的数据进行二次过滤,以减少模块之间传输的数据总量,减轻上层模块的数 据分析时间,再将数据通过指定数据传送通道发送到上层分析机子系统,做进一步的处 理。   分析机子系统作为整个系统的中间层,其作用在于对从底层接收到的原始数据记录 进行进一步的处理。主要是通过该层所包含的分析模块对采集到的原始数据,按照既存 于规则库中的规则,进行模式匹配分析,将正常授权访问与非法入侵行为区分开,并把 分析的结果存储到日志数据库中。对于危害操作进行报警。   控制台子系统作为人机交互的接口,为用户管理、控制、配置系统并查询入侵记录 提供操作界面。它负责控制、管理信息获取子系统和分析机子系统,生成安全规则,接 收、存储报警和日志信息;对报警及日志信息进行查询统计;对报警事件做进一步分析 处理,并且有开放的报警接口支持更高层次的安全管理平台。   2、纵向结构   从纵向看,与原有系统不同之处在于,新的数据库安全监控系统在采用获取一分析 一响应的体系结构,构建面向对象开发和面向构件开发的技术基础上,新引入了面向服 务框架思想,实现了获取与分析的分离,通信与业务的分离。其纵向结构如图2所示:   在整个系统中TCP/IP层,即物理网络层,作为底层存在于系统中,在其上构筑的通 信托管层则总揽了系统的全部通信工作,是整个系统的总线,支持异步通讯和断忘映传 。在这之上的业务托管层可视做所有业务的容器和管理平台,其中最重要的功能则是提 供信息注册,以实现信息生产者和信息消费者之间的沟通。在业务托管层的边缘是信息 网关,负责将业务数据按照标准协议转化成其他格式数据,以实现和其他系统(包括安 全设备)之间的互联、级联。最上层的是具体的业务模块,它们的角色分别为信息生产 者和信息消费者,其中信息获取可视做信息生产者,而分析则是信息消费者,响应是信 息的二次消费者,也是最终消费者。   传统的AAR框架与面向服务思想的结合,使得这四个层次相对独立,互相之间实现了 松祸合,并且因为托管平台也己成形,那么基于这一平台的响应业务插件的开发将会变 得非常便捷,从而实现了面向服务和面向构件开发的核心理念随需而变。   同时也实现了系统的分布式结构设计,集中控制与多层管理。整个系统由检测系统 、分析系统、控制系统组成,每个子系统都采用层次化设计,业务逻辑与通讯管理分层 实现。一个控制系统可以管理多个分析系统,一个分析系统还可以同时支持多达五十个 不同系统平台的检测系统。 3、切向结构   若从切面来观察该系统,新系统的关键脉络变得更加清晰明了,两条关键脉络包括 :数据和命令,而且互相内部之间实现了高聚合、松祸合,提高了模块的独立化。这里 的数据为狭义数据,主要包括了信息生产者向信息消费者提供的信息,而命令则是响应 模块对于获取和分析模块进行配置、维护、管理所传送的信息。数据(包括报警数据和 实时信息)始终是自下而上的,从被监控数据库采集出来,途经IAS,AES,最后到达MT S。而命令(控制)始终是自上而下的,其中一部分命令由MTS发起(因用户的操作发起 或系统维护需要发起)途经AES,最后到达IAS;另一部分由AE发起(因系统维护需要发 起)到达IAS。   二、系统工作原理   该系统是一种基于主机探测的实时自动攻击识别和响应系统,运行于有敏感数据需 要保护内部网络中。通过采取主机监控的方式,获取用户的数据库操作信息。借助于自 身内置的攻击特征数据库,识别违反用户定义的安全规则,进行应用级攻击检查。在寻 找到攻击模式和其他违规活动时,可以进行如下反应:控制台告警

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值