楼主: iloveora

把一个表的列值转为显示的列标题,如何实现

[复制链接]
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
11#
 楼主| 发表于 2005-1-13 14:01 | 只看该作者
我用这种方式试验过,完全正确的,就是有一个小问题
这样插入到table_b里,结果将是
type err1 err2 right
1     15   0      0
1     0     28    0
2    12    0      0
2    0      0      5
3    0     10     0
而不是我想要的把type=1的列变为一行
type err1 err2 right
1 15 28 0
2 12 0 5
3 0 10 0

我原来的做法是用建表table_b的方法再建一个表table_c
然后          insert into table_c (type,err1,err2,right)
                 select type,nvl(max(err1),0),nvl(max(err2),0),nvl(max(right),0)  from table_b group by type
但这样做显然不是动态实现的,很不好,我也想不出别的好办法,动态sql实在是不熟


最初由 rollingpig 发布
[B]This one will better
[php]
create table table_b (type number)
/
begin
for a in (select distinct status from table_a ) loop
        execute immediate
                'alter table table_b add ( '||a.status ||' number default 0)';
end loop;
for a in (select type,status,amount from table_a ) loop
        execute immediate
                'insert into table_b (type,'||a.status||')
                values(:1,:2)' using a.type,a.amount;
end loop;
end ;
/
[/php] [/B]

使用道具 举报

回复
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
12#
 楼主| 发表于 2005-1-13 14:30 | 只看该作者
jaunt版主给的两个链接实在没看懂,水平未到...尤其是老外提供的那个语句...

使用道具 举报

回复
论坛徽章:
23
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:58马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:58
13#
发表于 2005-1-13 14:31 | 只看该作者
最初由 iloveora 发布
[B]我用这种方式试验过,完全正确的,就是有一个小问题
这样插入到table_b里,结果将是
type err1 err2 right
1     15   0      0
1     0     28    0
2    12    0      0
2    0      0      5
3    0     10     0
而不是我想要的把type=1的列变为一行
type err1 err2 right
1 15 28 0
2 12 0 5
3 0 10 0

我原来的做法是用建表table_b的方法再建一个表table_c
然后          insert into table_c (type,err1,err2,right)
                 select type,nvl(max(err1),0),nvl(max(err2),0),nvl(max(right),0)  from table_b group by type
但这样做显然不是动态实现的,很不好,我也想不出别的好办法,动态sql实在是不熟


[/B]



type err1 err2 right
1     15   0      0
1     0     28    0
2    12    0      0
2    0      0      5
3    0     10     0
的基础上,再:
select type, sum(err1) as err1, sum(err2) as err2, sum(right) as right
from table_b
group by type
到是可以得到你想要的结果。

使用道具 举报

回复
论坛徽章:
10
授权会员
日期:2005-10-30 17:05:332010年世界杯参赛球队:科特迪瓦
日期:2010-04-15 12:20:472010年世界杯参赛球队:智利
日期:2010-04-13 17:15:21生肖徽章2007版:蛇
日期:2009-09-24 13:54:11生肖徽章2007版:龙
日期:2009-09-22 13:56:012009日食纪念
日期:2009-07-22 09:30:00生肖徽章2007版:龙
日期:2009-02-10 13:45:15生肖徽章2007版:狗
日期:2009-02-03 13:53:34会员2006贡献徽章
日期:2006-04-17 13:46:34ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28
14#
发表于 2005-1-13 14:37 | 只看该作者
如果table_b允许drop的话,只要构建两个动态SQL就行了:
第一个:
Exceute immediate 'Drop table table_b';
第二个:
Execute immediate 'Create table table_b (...) Select ...';

使用道具 举报

回复
论坛徽章:
23
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:58马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:58
15#
发表于 2005-1-13 14:43 | 只看该作者
最初由 iloveora 发布
[B]jaunt版主给的两个链接实在没看懂,水平未到...尤其是老外提供的那个语句... [/B]


方法一(By nyfor):
create or replace type strings_table is table of varchar2(20);
/
create or replace function merge (pv in strings_table) return varchar2
is
  ls varchar2(4000);
begin
  for i in 1..pv.count loop
    ls := ls || pv(i);
  end loop;
  return ls;
end;
/
create table t (id number,name varchar2(10));
insert into t values(1,'Joan');
insert into t values(1,'Jack');
insert into t values(1,'Tom');
insert into t values(2,'Rose');
insert into t values(2,'Jenny');

select t0.id,merge(cast(multiset(select name from t where t.id = t0.id) as strings_table)) names
from (select distinct id from t) t0;

自己写的函数merge,主要作用就是把一个竖表变横表,函数很简单,就是使用了一个循环而已。

估计你是cast( multiset (...) ) 这一部分难以理解。
CAST converts one built-in datatype or collection-typed value into another built-in datatype or collection-typed value.
http://oraclesvca2.oracle.com/do ... 40/functions15a.htm

后面这个SQL中,t0 得到一个id 的列表,且每个id 只有一条记录。
子查询得到这个id 所对应的所有name,然后通过cast(multiset(...)) 把这个id 对应所有name 转换成自定义类型,然后再通过自己写的函数merge 将这个自定义类型由竖表转换成横表。

使用道具 举报

回复
论坛徽章:
23
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:58马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:58
16#
发表于 2005-1-13 14:51 | 只看该作者
最初由 iloveora 发布
[B]jaunt版主给的两个链接实在没看懂,水平未到...尤其是老外提供的那个语句... [/B]


老外这个主要是lead 的使用。
LEAD is an analytic function. It provides access to more than one row of a table at the same time without a self join. Given a series of rows returned from a query and a position of the cursor, LEAD provides access to a row at a given physical offset beyond that position.

http://download-west.oracle.com/ ... s60a.htm#SQLRF00656

老外这个的优点是只用了一个SQL,但是不足是必须事先知道同一个type 下最多有多少个status。

使用道具 举报

回复
论坛徽章:
131
2006年度最佳技术回答
日期:2007-01-24 12:58:48福特
日期:2013-10-24 13:57:422014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:142013年新春福章
日期:2013-02-25 14:51:24
17#
发表于 2005-1-13 16:57 | 只看该作者
try this :
[php]
begin
execute immediate
        'drop table table_b';
execute immediate
        'create table table_b (type number)';
for a in (select distinct status from table_a ) loop
        execute immediate
                'alter table table_b add ( '||a.status ||' number default 0)';
end loop;
for a in (select type,status,amount from table_a ) loop
        execute immediate
                'merge into table_b t_b using
                        (select :1 as type,:2 as amount from dual ) t_a
                on (t_b.type = t_a.type )
                when matched then
                        update set t_b.'||a.status||'=t_a.amount+t_b.'||a.status||'
                when not matched then
                        insert (type,'||a.status||') values(t_a.type,t_a.amount)'
        using a.type,a.amount;
end loop;
end ;
/

[/php]

使用道具 举报

回复
论坛徽章:
1
会员2006贡献徽章
日期:2006-04-17 13:46:34
18#
 楼主| 发表于 2005-1-14 10:22 | 只看该作者
谢谢各位!昨天一直忙于工作,没有时间回复
我试图用update if SQL%NOTFOUND then insert来做
就是第二个for in里把insert换成上面步骤
修改rollingpig的语句如下:

create table table_b (type number)
/
begin
for a in (select distinct status from table_a ) loop
        execute immediate
                'alter table table_b add ( '||a.status ||' number default 0)';
end loop;
for a in (select type,status,amount from table_a ) loop
        execute immediate
                'update table_b set '||a.status||'=:1 where type=a.type';
       if SQL%NOTFOUND then
        excute immediate        
               'insert into table_b (type,'||a.status||')
                values(:1,:2)' using a.type,a.amount;
end loop;
end ;

但这样做老是报错,说update那句column定义错误,a.type
我对动态sql实在不熟,这句话for a in(select type,status,amount from table_a) 即后面的引用a.mount我不明白这种是什么用法

使用道具 举报

回复
论坛徽章:
23
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-02-13 15:10:58马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:58
19#
发表于 2005-1-14 10:43 | 只看该作者
update 那句可以写成(你table_a 的type 字段和amount 都是数字型的话):

execute immediate
'update table_b set '||a.status||'=nvl ( '||a.status||' , 0 ) + '|| to_char(a.amount) ||' where type=' || to_char(a.type);

使用道具 举报

回复
论坛徽章:
168
马上加薪
日期:2014-02-19 11:55:142012新春纪念徽章
日期:2012-02-13 15:10:582012新春纪念徽章
日期:2012-01-04 11:49:54蜘蛛蛋
日期:2011-12-05 16:08:56ITPUB十周年纪念徽章
日期:2011-11-01 16:19:41设计板块每日发贴之星
日期:2011-07-22 01:01:02ITPUB官方微博粉丝徽章
日期:2011-06-30 12:30:16管理团队成员
日期:2011-05-07 01:45:082011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-01-25 15:42:33
20#
发表于 2005-1-14 14:25 | 只看该作者
看看下面的语句能否满足你的需求?

SQL> create table test_1
  2  (type number,status varchar2(20),amout number)
  3  /

表已创建。

SQL> insert into test_1
  2  values(1,'err1',15)
  3  /

已创建 1 行。

SQL> insert into test_1
  2  values(1,'err2',28)
  3  /

已创建 1 行。

SQL> insert into test_1
  2  values(2,'err1',12)
  3  /

已创建 1 行。

SQL> insert into test_1
  2  values(2,'right',5)
  3  /

已创建 1 行。

SQL> insert into test_1
  2  values(3,'err2',10)
  3  /

已创建 1 行。

SQL> commit
  2  /

提交完成。

SQL>
SQL> select type,
  2  sum(decode(status,'err1',amout,0)) err1,
  3  sum(decode(status,'err2',amout,0)) err2,
  4  sum(decode(status,'right',amout,0)) right
  5  from test_1
  6  group by type
  7  /

      TYPE       ERR1       ERR2      RIGHT
---------- ---------- ---------- ----------
         1         15         28          0
         2         12          0          5
         3          0         10          0

SQL>
SQL>

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表