• sql 行转列


    1、 强大的group by

    1 select stdname,
    2 isnull(sum( case stdsubject when ' 化学 ' then Result end), 0 ) [化学],
    3 isnull(sum( case stdsubject when ' 数学 ' then Result end), 0 ) [数学],
    4 isnull(sum( case stdsubject when ' 物理 ' then Result end), 0 ) [物理],
    5 isnull(sum( case stdsubject when ' 语文 ' then Result end), 0 ) [语文]
    6 from #student
    7 group by stdname

    在这里,group by与sum + case结合,可以将表1中的记录(行)变成表2的字段(列)。Sum里面如果没有case,那么出来的值,只能是全部科目的总和,用了case以后,就是某科的成绩;然后这里用了好几个sum,每个科目一个sum,于是表1中本来某人某科占一条记录的"行"就变成了表2里某人一条记录,每科做一个字段了。


    这种心思巧妙和对语法的熟练运用让人击节赞叹。


    2、 利用select from (select from)的模式生成SQL语句

    1 declare @sql varchar( 4000 )
    2 set @sql = ' select stdname '
    3 select @sql = @sql + ' ,isnull(sum(case stdsubject when ''' + stdsubject + ''' then Result end),0) [ ' + stdsubject + ' ] '
    4 from (select distinct stdsubject from #student) as a
    5 select @sql = @sql + ' from #student group by stdname '
    6 print @sql
    7 exec(@sql)


    为了自动写上所有的科目,这里先将科目信息提炼出来:

    4 from (select distinct stdsubject from #student) as a

    利用之拼接生成SQL语句。当然现实中,如果#student表很大,这种做法并不妥,应该都有一个专门的科目类别表的。


    3、 在临时库中提炼出字段名。临时表是真实存在的表,保存在[tempdb]中,可以利用object_id('tempdb.dbo.表名')的方式获得字段信息。

    ============================================

    附录:

    http://www.cnblogs.com/zhanglei644213943/archive/2009/12/27/1633356.html


    纵览各大社区、论坛,各大 ORM框架火得不行了,如NHibernate、LINQ to SQL、ADO.NET Entity framework等,还有最近市场上出版的一本叫《领域驱动设计与模式实战》,里面也凸显了不少NHibernate在领域驱动设计中的作用与地位,也算是第一本与NHibernate相关的书籍吧!不过就NHibernate而言还是没有官方文档介绍得详细呵呵,园子里Kiler 已经把他翻译成中文版的了,收益一大片仅仅是CET-4的人。不管你是用NHibernate也好,还是用LINQ to SQL也好,用profiler一跟踪,执行的都是SQL语句,所以所SQL是根。特别是对于那些以数据为中心的应用系统,在数据库中实现复杂的存储过程,复杂的报表查询,还是直接SQL来得痛快。当然 对于那些在基于.NET的中间层应用中,它们实现面向对象的业务模型和商业逻辑的应用,NHibernate是最有用的。不管怎样,NHibernate一定可以帮助你消除或者包装那些针对特定厂商的SQL代码,并且帮你把结果集从表格式的表示形式转换到一系列的对象去(官方文档)。

    有点跑题了,不再啰嗦----直接晾出压轴题。

    压轴题第一问

    1.把表一转换为表二

    表一:

    表二:

    数据库代码如下:

    代码
    1 DROP table #student
    2 CREATE TABLE #student (stdname nvarchar( 10 ),stdsubject nvarchar( 10 ),result int )
    3 INSERT INTO #student VALUES ( ' 张三 ' , ' 语文 ' , 80 )
    4 INSERT INTO #student values ( ' 张三 ' , ' 数学 ' , 90 )
    5 INSERT INTO #student VALUES ( ' 张三 ' , ' 物理 ' , 85 )
    6 INSERT INTO #student VALUES ( ' 李四 ' , ' 语文 ' , 85 )
    7 INSERT INTO #student values ( ' 李四 ' , ' 数学 ' , 92 )
    8 INSERT INTO #student VALUES ( ' 李四 ' , ' 物理 ' , 82 )
    9 INSERT INTO #student VALUES ( ' 李四 ' , ' 化学 ' , 82 )
    10 INSERT INTO #student VALUES ( ' 李四 ' , ' 化学 ' , 82 )
    11 SELECT * FROM #student
    可能很多老手们,一看到这题目就有了答案。当然,贴出答案来不是我的目的,我要带着SQL新手们重构到答案。用MVP李建忠老师最爱说的话就是------我不建议一上来就套用模式,而应该从重构到模式。

    首先大家会想到分两组

    1 select stdname,····,from #student group by stdname
    然后······中间该写什么呢?

    代码
    1 case stdsubject when ' 化学 ' then Result end
    2 case stdsubject when ' 语文 ' then Result end
    3 case stdsubject when ' ··· ' then Result end
    4 case stdsubject when ' ··· ' then Result end
    5 case stdsubject when ' ··· ' then Result end
    表二里面得0是哪里来的呢?

    代码
    1 isnull(sum( case stdsubject when ' 化学 ' then Result end), 0 )
    2 isnull(sum( case stdsubject when ' 语文 ' then Result end), 0 )
    3 isnull(sum( case stdsubject when ' ··· ' then Result end), 0 )
    4 isnull(sum( case stdsubject when ' ··· ' then Result end), 0 )
    5 isnull(sum( case stdsubject when ' ··· ' then Result end), 0 )
    所以得出:

    代码
    1 select stdname,
    2 isnull(sum( case stdsubject when ' 化学 ' then Result end), 0 ) [化学],
    3 isnull(sum( case stdsubject when ' 数学 ' then Result end), 0 ) [数学],
    4 isnull(sum( case stdsubject when ' 物理 ' then Result end), 0 ) [物理],
    5 isnull(sum( case stdsubject when ' 语文 ' then Result end), 0 ) [语文]
    6 from #student
    7 group by stdname
    然后得出答案:

    代码
    1 declare @sql varchar( 4000 )
    2 set @sql = ' select stdname '
    3 select @sql = @sql + ' ,isnull(sum(case stdsubject when ''' + stdsubject + ''' then Result end),0) [ ' + stdsubject + ' ] '
    4 from (select distinct stdsubject from #student) as a
    5 select @sql = @sql + ' from #student group by stdname '
    6 print @sql
    7 exec(@sql)
    8
    压轴题第二问:把表二转化为表一

    表一:

    表二:

    数据库代码如下:

    代码
    1 DROP table #student2
    2 CREATE TABLE #student2 (stdname nvarchar( 10 ),化学 int ,数学 int ,物理 int ,语文 int )
    3 INSERT INTO #student2 VALUES ( ' 李四 ' , 164 , 92 , 82 , 85 )
    4 INSERT INTO #student2 VALUES ( ' 张三 ' , 0 , 90 , 85 , 80 )
    5 SELECT * FROM #student2
    看到这题,直接想到:

    代码
    1 SELECT ' 李四 ' as stdname,stdname = ' 化学 ' , 化学 as result from #student2 where stdname = ' 李四 '
    2 union all
    3 SELECT ' 李四 ' as stdname,stdname = ' 数学 ' , 数学 as result from #student2 where stdname = ' 李四 '
    4 union all
    5 SELECT ' 李四 ' as stdname,stdname = ' 物理 ' , 物理 as result from #student2 where stdname = ' 李四 '
    6 union all
    7 SELECT ' 李四 ' as stdname,stdname = ' 语文 ' , 语文 as result from #student2 where stdname = ' 李四 '
    8 union all
    9 SELECT ' 张三 ' as stdname,stdname = ' 化学 ' , 化学 as result from #student2 where stdname = ' 张三 '
    10 union all
    11 SELECT ' 张三 ' as stdname,stdname = ' 数学 ' , 数学 as result from #student2 where stdname = ' 张三 '
    12 union all
    13 SELECT ' 张三 ' as stdname,stdname = ' 物理 ' , 物理 as result from #student2 where stdname = ' 张三 '
    14 union all
    15 SELECT ' 张三 ' as stdname,stdname = ' 语文 ' , 语文 as result from #student2 where stdname = ' 张三 '
    重构到:

    代码
    1 declare @sql2 varchar( 4000 )
    2 set @sql2 = ''
    3 SELECT @sql2 = @sql2 +
    4 ' SELECT ''' + stdname + ''' as stdname,stdname= '' 化学 '' , 化学 as result from #student2 where stdname= ''' + stdname + '''
    5 union all
    6 SELECT ''' +stdname+ ''' as stdname,stdname = '' 数学 '' , 数学 as result from #student2 where stdname = ''' +stdname+ '''
    7 union all
    8 SELECT ''' +stdname+ ''' as stdname,stdname = '' 物理 '' , 物理 as result from #student2 where stdname = ''' +stdname+ '''
    9 union all
    10 SELECT ''' +stdname+ ''' as stdname,stdname = '' 语文 '' , 语文 as result from #student2 where stdname = ''' +stdname+ ''' union all '
    11 from (SELECT stdname FROM #student2) as a
    12 SELECT @sql2 = LEFT(@sql2,LEN(@sql2) - 10 )
    13 PRINT(@sql2)
    14 exec(@sql2)
    如果要求不能出现 化学 数学 物理 语文 这样的关键字,那么可以这样写:

    代码
    1 select [name] into #tmpCloumns
    2 from tempdb.dbo.syscolumns
    3 where id = object_id( ' tempdb.dbo.#student2 ' )
    4 and [name] <> ' stdname '
    5 select * from #tmpCloumns
    6
    7 declare @strSql nvarchar( 800 )
    8 select @strSql = ''
    9 select @strSql = @strSql + ' union all ' + char ( 10 ) + char ( 13 ) +
    10 ' select [stdname], ''' + [name] + ''' as [科目],[ ' + [name] + ' ] ' + char ( 10 ) + char ( 13 ) +
    11 ' from [#student2] ' + char ( 10 ) + char ( 13 )
    12 from #tmpCloumns
    13
    14 select @strSql = substring(@strSql, 11 ,len(@strSql)) + ' order by stdname,[科目] '
    15 -- print @strSql
    16 exec(@strsql)

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/leftfist/archive/2009/12/29/5097307.aspx

  • 相关阅读:
    MyEclipse中的Tomcat跑大项目时内存溢出:permgen space
    MyEclipse新建工作空间后的配置详细步骤
    解决eclipse复制粘贴js代码卡死的问题
    eclipse复制工作空间配置
    maven项目检出后报错(包括编译报错和运行报错)的常见检查处理方式
    MyEclipse中引用的maven配置文件只访问私服的配置
    图标网站
    afasf
    一个权限管理模块的设计(转载)
    奇艺下载
  • 原文地址:https://www.cnblogs.com/oneroom/p/1652636.html
Copyright © 2020-2023  润新知