zoukankan      html  css  js  c++  java
  • 学习普通行列转换(2000)

    (转至CSDN-爱新觉罗.毓华)
    坚持SQL Server的学习, 列转行这个也是比较常见SQL操作
    本人愚见, 总结出来具有以下条件的情况下可能会出现此需求: 一个表中某一个列值依赖于该表中两个或多个列(如下表中的成绩依赖于学生和课程),  好像这种情况违反了数据库设计的第一范式(1NF), 哈哈!
    今天CSDN上无意看到一个比较全面的列转行, 但是以前没怎么接触心里就有种恐惧,现在系统的学习下,避免以后遇见相同的问题的又束手无策了!
    还是开始创建测试环境
     
    use tempdb;
    go
    if object_id('tb'is not null
        
    drop table tb
    go
    create table tb(name varchar(10) , course varchar(10) , scores int)
    insert into tb values('张三' , '语文' , 74)
    insert into tb values('张三' , '数学' , 83)
    insert into tb values('张三' , '物理' , 93)
    insert into tb values('李四' , '语文' , 74)
    insert into tb values('李四' , '数学' , 84)
    insert into tb values('李四' , '物理' , 94)
    go
    select * from tb
     
    挺简单的一张表,描述了学生的课程成绩信息,其中有3个字段,依次是姓名,课程,分数
    测试数据中有2个学生,分别是张三和李四,而课程有语文,数学,物理3课,查询结果集如下
     
     
    现有这一需求, 将成绩转为行显示,学科为列, 结果如下
     
     
    结果改变了什么, 行数改变了,跟学生数量有关,一个学生一行,这里就肯定是用学生姓名来分组了
    除姓名外,增加了3列,跟课程数量有关,根据不同的课程创建新列, 这里就是用 "case when"了,代码如下:

     

    • SQL 2000实现

    --静态实现

    select name 姓名, 
    max(case course when '语文' then scores end) 语文,
    max(case course when '数学' then scores end) 数学,
    max(case course when '物理' then scores end) 物理
    from tb
    group by name
     
    这里的then后的值都是成绩, 没有区别; 只是条件不同, 属于哪一科的成绩就放在那一列下, 因为是逐行扫描, 每次只有单个成绩, 所以这里的max函数只是为了骗过group分组的幌子, 没有任何意义, 执行查询结果如上所示
     
    现将需求稍微小小改变一下, 课程为行学生为列成绩不变在中间, 其实这与上面的一个问题类似, 都是将成绩以行的形式显示, 只是"case when" 和 group不一样而已, 知道原理了, 稍微变通一下, 应该没问题, 哈哈!
     
    select course 课程, 
    max(case name when '张三' then scores end) 张三,
    max(case name when '李四' then scores end) 李四
    from tb
    group by course
     
    --动态实现
    以上虽然实现了功能, 但是比较死板, 它是静态的, 也就是课程只允许有语文, 数学, 物理, 若增加了其他课程就不行了, 这样我们得动态生成sql语句, 才能根据不同的课程生成不同的sql, 然后执行, 以前从未接触了动态生成sql, 呵呵! 这次看到了才发现了sql编程与开发语言编程有异曲同工之妙, 请看下面动态生成的SQL语句
     
    declare @sql varchar(8000)
    set @sql = 'select name 姓名'
    select @sql = @sql + ' , max(case course when ''' + course + ''' then scores else 0 end) ' + course + ''
    from (select distinct course from tb) as a
    set @sql = @sql + ' from tb group by name'
    print @sql 
      
     
    动态拼接后的语句与我们之前手写的结果一样, 然后通过系统存储过程sp_executesql执行, 进行sql查询, 效果一样, 这里用的一个技巧是select @sql变量赋值,  获取去重后所有的科目的集合, 然后循环动态构造case when语句添加到@sql变量后面,  达到我们想要的效果, 这样也能正确执行. 下次再来看看SQL 2005中的实现
  • 相关阅读:
    CentOS 阿里源
    使用分区挂载 ftp 目录
    Docker-compose常用命令
    docker 启动容器失败 id already in use
    Docker daemon.json 的配置项目合集
    Watchtower
    umount 时目标忙解决办法
    opencontrail 参考资料
    使用disk-image-builder(DIB)制作Ironic 裸金属镜像
    Nodejs常见安装
  • 原文地址:https://www.cnblogs.com/fengxiang/p/1543833.html
Copyright © 2011-2022 走看看