关于竖表转横表的问题

问题

关于竖表转横表的问题
                                                                                本文作者:dinya
内容摘要:在开发过程,经常遇到一些将表的显示方式进行转换的需求,我们习惯性称之为竖表到横表的转换,本文通过一个例子来简要说明常见的两种竖表转横表的问题。

本文适宜读者范围:Oracle初级,中级

系统环境:

      OS:windows 2000 Professional (英文版)

Oracle:8.1.7.1.0

正文:

在实际的应用中,我们经常遇到需要转换数据显示方式,比如将横表转为竖表,或将竖表转换为横表的情况,如:课程表的显示方式,部门平均工资的排名等情况。下面将将根据两个实例子的需求描述给出两种常见的竖表转横表的解决办法(本例中的数据意思是:一、二、三年级的各科目最高分统计)。

表结构:

create table test_table
(
    grade_id number(8),             --年级:1、一年级,2、二年级,3、三年级
    subject_name varchar2(30),    --科目:包含语文、数学、外语、政治等科目
    max_score number(8)             --最高分
)

表中数据:

SQL> select * from test_table;

 GRADE_ID    SUBJECT_NAME                   MAX_SCORE

        1      语文                                  95

        1      数学                                  98

        2      语文                                  86

        2      数学                                  90

        2      政治                                  87

        3      语文                                  93

        3      数学                                  88

        3      英语                                  88

        3      政治                                  97

9 rows selected.

 

第一种转换方式:

需求描述:查看每个年级在系统中存在的科目信息,并各年级的科目信息按下面的格式显示:

GRADE_ID      SUBJECT_NAME  

         1      语文  数学

    2      语文  数学  政治

     3      语文  数学  英语  政治

分析:在要求得到的结果中,每个年级的科目将变成一条记录,而且每个年级的科目是不固定的。所以考虑写个函数来解决,输入年级信息,使用游标得到该年级的所有科目信息并返回值。

1、建函数:

SQL> create or replace function test_fun(p_grade number) return varchar2 as

  2      v_temp varchar2(100):='';

  3      v_out varchar2(500):='';

  4      cursor c is select a.subject_name from test_table a where a.grade_id=p_grade;

  5  begin

  6      open c ;   --打开游标

  7      loop

  8          fetch c into v_temp;

  9          exit when c%notfound;

 10          v_out:=v_out||'  '||v_temp;

 11      end loop;

 12      close c;      --关闭游标

 13      return v_out;

 14      exception

 15          when others then

 16              return 'An error occured';       

 17  end ;

 18  /

Function created.

 

SQL> create or replace function test_fun(p_grade number) return varchar2 as

  2      v_out varchar2(500):='';

  3      cursor c is select a.subject_name from test_table a where a.grade_id=p_grade;

  4  begin

  5      for v_temp in c loop

  6          v_out:=v_out||'  '||v_temp.subject_name;

  7      end loop;       --系统自动关闭游标

  8      return v_out;

  9      exception

 10          when others then

 11              return 'An error occured';

 12  end ;

 13  /

Function created.

 

2、调用函数得到输入结果:

SQL> select distinct a.grade_id,test_fun(a.grade_id) subject from test_table a;

 GRADE_ID            SUBJECT

1        语文  数学

2         语文  数学  政治

3         语文  数学  英语  政治

 

第二种转换方式:

需求描述:要求将表中的年级、科目及最高的信息按照下表的格式显示,如果该年级没开的课程,则其最高分用0表示:

年级       语文          数学         英语      政治

一年级        95           98            0               0

二年级        86           90            0              87

三年级        93           88           88              97

 

分析:该需求将年级的分数及科目信息由纵向转为横向,这样就要针对每个年级的,对其科目进行判断,存在科目则显示科目的最高分,如果不存在显示0。这时候就考虑到使用decode函数来解决。实现如下:

 select
    decode(t.grade_id,1,'一年级',2,'二年级',3,'三年级') 年级,
    sum(decode(t.subject_name,’语文’,t.max_score,0)) 语文,
    sum(decode(t.subject_name,'数学',t.max_score,0)) 数学,
    sum(decode(t.subject_name,'英语',t.max_score,0)) 英语,
    sum(decode(t.subject_name,'政治',t.max_score,0)) 政治
from
    test_table t
group by
    t.grade_id

 

需要说明的是,在第一种转换方式中写了两个函数,两个函数实现的是同一个需求,所不同的是,两个函数中游标使用方式不同,地一个函数中手动打开游标,循环结束后要求手动关闭。而后一个函数使用for 循环,循环结束后系统自动关闭光标。在第二种转换方式中,使用了decode函数,关于decode的详细用法,请参考oracle函数相关文档。

总  结:

上面的两种转换方式是在开发中经常遇到的情况,在开发中的其他类似的转换都可以参考上面的转换方式,使用decode,nvl等函数进行一些特别的处理即可得到想要的显示方式.
本文你可以在作者的Blog上找到,更多内容请登陆作者的Blog。

作者Blog:  http://blog.csdn.net/dinya2003/
如转载,请保留作者Blog信息.

时间: 2024-08-03 02:23:20

关于竖表转横表的问题的相关文章

在.NET中,将竖表变横表(支持固定列)

竖表变横表(支持固定列) 根据LoveCherry的竖变横方法改进而来        public DataTable MakeData(DataTable dt,int iColumnSize,int[] iColumnID) //iColumnsize:重复列数 iColumnID 需要横向排列的列的序号数组        {               int ColumnCount=iColumnID.Length;            int totalRows=dt.Rows.Co

sql2005-请教大神 SQL2005纵表变横表的问题!求指导!

问题描述 请教大神 SQL2005纵表变横表的问题!求指导! 怎么将表一 变成表二格式啊! SQL数据库!求大神指点!! 解决方案 select iddecode(id'1''车间''2''班组')sum(decode(星期'4'预算0)) 星期四预算sum(decode(星期'4'实际0)) 星期四实际....(类推) from 表1 group by id; 解决方案二: 感谢大神指点,decode函数SQL里没有,不过我查了一下,有case then 按照你的格式些出来了,谢谢啊!

SQL Server纵表与横表相互转换的方法_MsSql

1,纵表转横表 纵表结构 Table_A: 转换后的结构: 纵表转横表的SQL示例: SELECT Name , SUM(CASE WHEN Course = N'语文' THEN Grade ELSE 0 END) AS Chinese , SUM(CASE WHEN Course = N'数学' THEN Grade ELSE 0 END) AS Mathematics , SUM(CASE WHEN Course = N'英语' THEN Grade ELSE 0 END) AS Engl

SQL Server纵表与横表相互转换的方法

1,纵表转横表 纵表结构 Table_A: 转换后的结构: 纵表转横表的SQL示例: SELECT Name , SUM(CASE WHEN Course = N'语文' THEN Grade ELSE 0 END) AS Chinese , SUM(CASE WHEN Course = N'数学' THEN Grade ELSE 0 END) AS Mathematics , SUM(CASE WHEN Course = N'英语' THEN Grade ELSE 0 END) AS Engl

C# DataTable 纵表转横表

问题描述 DATATABLE1表结构:FLAGCODEVALUE1A1002A903A801B882B753B96转换为DATATABLE2表结构FLAGCODE1CODE2AB1100882907538096前台转换非数据库.怎么转换效率最高,最好有代码 解决方案 解决方案二:用linq,分组合并.解决方案三:给一个我以前回答的,你参考下:http://topic.csdn.net/u/20110620/15/bec4adee-ebd6-40c7-88f6-250050f79680.html解

横表与竖表性能浅析

概念介绍 横表概念   横表就是普通的建表方式,每一个字段代表一个KPI指标.举个列子,一个学生的成绩表:学号.数学成绩.语文成绩.英语成绩. 物理成绩.化学成绩......如下所示: SQL> DESC STUDENT_SCORE Name Type Nullable Default Comments ---------------- ---------- -------- ------- -------- STUDENT_NO NUMBER(10) 学号 CHINESE_SCORE NUMB

SQL 查询横表变竖表

首先是三张表, CNo对应的是课程,在这里我就粘贴了.                                           主表                  人名表 按照常规查询 SELECT s.SName, c.CName,s2.SCgrade   FROM S s INNER JOIN SC s2 ON s2.SNo = s.SNo INNER JOIN C c ON c.CNo = s2.CNo 那么结果是这样的   但是这是横表 不是我想看到的结果. 我们要看到这

sqlserver中查询横表变竖表的sql语句简析

首先是三张表, CNo对应的是课程,在这里我就粘贴了. 主表 人名表 按照常规查询 SELECT s.SName, c.CName,s2.SCgrade FROM S s INNER JOIN SC s2 ON s2.SNo = s.SNo INNER JOIN C c ON c.CNo = s2.CNo 那么结果是这样的 但是这是横表 不是我想看到的结果. 我们要看到这样的结果: 那么怎么办呢?第一种写法: 复制代码 代码如下: SELECT w.SName, sum(case when w.

--竖表变行表

--竖表变行表--创建表create table A(工号 varchar(20),日期 smalldatetime,时间 varchar(20))--插入测试数据insert into A select '01', '2004-10-01', '07:50'union select '01', '2004-10-01', '11:35'union select '01', '2004-10-01', '14:20'union select '01', '2004-10-02', '08:01'