前几天做一调查,需要下边这样的一个转换。

求一SQL--关于数据纵横转换的

假设表A中有以下数据

A1 1 01

A1 1 02

A1 1 03

A2 1 01

A2 2 01

A2 2 02

现希望一SQL能够查出下边这样的数据(暂时假设表A中第三列只有01-03这三种可能值)

A1 1 01-02-03

A2 1 01

A2 2 01-02

后来看过别人SQL后,我想出了这么一个笨招。

另外根据tanfufasql,我下午在回家的路上突然想到了一个方法,就是第三列几个字符串,但完全可以定种规则转成一些数字,譬如01成数字1,02成数字2,03成数字4,04话转成数字8,依此推。

然后group sum,根据sum就可以推知是由哪几个字符串值组成的了。

这种方法恐怕就是解析sum值这块需要花费过多的代了。另外不知道db2中有无将十制数字成二制的函数。

所以又了我昨的想法,已经测试成功了。放出其中个最重要的函数,主要是实现转换和解析个二

 

CREATE FUNCTION DB2ADMIN.DEC(VAL_SUM INTEGER)

RETURNS     VARCHAR(20)

    LANGUAGE SQL

    DETERMINISTIC

    NO EXTERNAL ACTION

    CONTAINS SQL

    INHERIT SPECIAL REGISTERS

   

 

   BEGIN ATOMIC

     DECLARE @PARA INT;

    DECLARE @DIV INT;

    DECLARE @MOD INT;

    DECLARE @BIN varchar(20);

    DECLARE @RET varchar(30);

    SET @BIN = '';

    SET @RET = '';

   

    SET @PARA = VAL_SUM;

   

    SET @DIV =@PARA/2;

    SET @MOD = MOD(@PARA,2);

   

    WHILE @PARA <> 0 DO

   

       SET @BIN = rtrim(ltrim(char(@MOD))) || rtrim(ltrim(@BIN));

       SET @PARA = @PARA/2;

       SET @DIV =@PARA/2;

       SET @MOD = MOD(@PARA,2);

    END WHILE;

 

   

    SET @BIN = REPEAT('0',10 - length(@BIN)) || @BIN;

    

    IF substr(@BIN,1,1) = '1' THEN

     SET  @RET = 'NW';

    END IF;

   

        IF substr(@BIN,2,1) = '1' THEN

     SET  @RET = @RET || '-' || 'RE';

    END IF;

   

        IF substr(@BIN,3,1) = '1' THEN

     SET  @RET = @RET || '-' || 'RB';

    END IF;

   

        IF substr(@BIN,4,1) = '1' THEN

    SET  @RET = @RET || '-' || 'RF';

    END IF;

   

        IF substr(@BIN,5,1) = '1' THEN

    SET  @RET = @RET || '-' || 'SV';

    END IF;

   

        IF substr(@BIN,6,1) = '1' THEN

     SET  @RET = @RET || '-' || 'NP';

    END IF;

   

        IF substr(@BIN,7,1) = '1' THEN

     SET  @RET = @RET || '-' || 'NC';

    END IF;

   

        IF substr(@BIN,8,1) = '1' THEN

     SET  @RET = @RET || '-' || 'CC';

    END IF;

   

        IF substr(@BIN,9,1) = '1' THEN

     SET  @RET = @RET || '-' || 'DC';

    END IF;

   

        IF substr(@BIN,10,1) = '1' THEN

     SET  @RET = @RET || '-' || 'AD';

    END IF;

   

    IF length(@RET) > 0 THEN

     IF substr(@RET,1,1) = '-' THEN

       SET @RET = substr(@RET,2);

     END IF;

    END IF;

 

    RETURN rtrim(ltrim(@RET));

  END

 

;

接着呢,我这块砖就引出了玉。呵呵。

关于db2递归的一个例子

myfriend2010

ORACLE中大家可能对递归(在oracle中很多人称作家族树)已经很熟悉,因为ORACLE中的递归比较简单,也容易掌握!刚接触DB2的时候,也碰到过递归的问题,因为研究的人少所以刚接触的时候,对db2有一种神秘的感觉,db2是很强大的这个误用质疑!就sql而言,凡是oracle用sql能实现的,db2肯定或多或少也可以实现,只是逻辑复杂点!因为一直有人提问这边的问题,所以今天抽时间写了一点

首先,关于db2的递归的一点基础知识:

db2中的递归查询使用with来实现,也称为公共表达式,公共表达式在select语句的开始部分采用with子句的形式,在使用公共表达式的查询中可以多次使用它,并且公共表达式还可以通过取别名来连接到他本身,这样的话就可以达到循环的目的。

递归查询通常有3个部分需要定义:

一:一个公共表达式形式的虚拟表。

二:一个初始化表。

三:一个与虚拟表进行完全内连接的辅助表。

需要使用UNION all合并上边3个查询,然后用select从递归输出中得到最终的结果。

大体上如下形式

with XX(x1,x2,x3) as  -------@0

(

select a.s,a.s1 from a  ----@1

union all  ----@2

select * from a,xx where a.s=xx.x1 ------@3

)

select ... from xx where .... -------@4

@0:为with体,即虚拟表

@1:为初始化表,这里需要定义初始化的一些行,也就是你递归的出发点,或者说父行,这部分逻辑只执行一次,它的结果作为虚拟表递归的初始化内容。

@2:这里必须用UNION all

@3:这里需要定义递归的条件(辅助表),这里定义递归的逻辑,需要注意的是父行和子行进行连接的时候逻辑一定要清楚父子关系,不然很容易变成死循环的,这里首先将初始化表的结果作为条件进行查询,在把执行的结果添加到虚拟表中,只要这里能查询出来记录,那么就会进行下一步递归循环。

@4:这里就是对虚拟表的查询语句。

关于关于递归更多的知识,可以到google中找更专业的资料,这里只讲我理解的一些东西。

这里举一个简单点的例子:

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

Q:求一SQL--关于数据纵横转换的

假设表A中有以下数据

A1 1 01

A1 1 02

A1 1 03

A2 1 01

A2 2 01

A2 2 02

现希望一SQL能够查出下边这样的数据(暂时假设表A中第三列只有01-03这三种可能值)

A1 1 01-02-03

A2 1 01

A2 2 01-02

A:这个查询牵扯到全表的递归循环,用一般的sql语句很难搞定!

这是我刚写的一个递归语句!分享给大家看看!

因为懒,所以把建立测试表的逻辑也略去了,这里用with来生成上边的测试数据。

with t (t1,t2,t3) as (

values

('A1', 1 ,'01'),('A1' ,1, '02'),('A1', 1, '03'),

('A2', 1, '01'),('A2', 2, '01'),('A2', 2 ,'02')

)

select * from t;

测试一下:

C:\>db2 connect to dw

数据库连接信息

数据库服务器         = DB2/NT 8.2.0

SQL 授权标识         = DB2ADMIN

本地数据库别名       = DW

C:\>db2 with t (t1,t2,t3) as ( \

db2 (cont.) => values \

db2 (cont.) => ('A1', 1 ,'01'),('A1' ,1, '02'),('A1', 1, '03'), \

db2 (cont.) => ('A2', 1, '01'),('A2', 2, '01'),('A2', 2 ,'02') \

db2 (cont.) => ) \

db2 (cont.) => select * from t

T1 T2          T3

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

A1           1 01

A1           1 02

A1           1 03

A2           1 01

A2           2 01

A2           2 02

6 条记录已选择。

现在公布递归逻辑,sql如下:

with t (t1,t2,t3) as (

values

('A1', 1 ,'01'),('A1' ,1, '02'),('A1', 1, '03'),

('A2', 1, '01'),('A2', 2, '01'),('A2', 2 ,'02')

),

t1(t11,t22,t33,t44,t55) as (

select t1,t2,t3,rownumber() over(partition by t1,t2),rownumber() over(partition by t1,t2) as t4 from t

),

t3(s1,s2,s3,s4,s5) as(

select t11,t22,cast(t33 as varchar(100)),t44,t55 from t1 where T44 =1 and t55=1

union all

select a.s1,a.s2,cast(a.s3||'-'||b.t33 as varchar(100)),a.s4+1,a.s5 from t3 a,t1 b

where a.s1=b.t11 and a.s4 = b.t55-1)

select s1,s2,s3 from t3 x where x.s4=(select max(s4) from t3 y where x.s1=y.s1) order by s1,s2

;

测试一下:

C:\>db2 connect to dw

数据库连接信息

数据库服务器         = DB2/NT 8.2.0

SQL 授权标识         = DB2ADMIN

本地数据库别名       = DW

C:\>db2 with t (t1,t2,t3) as ( \

db2 (cont.) =>  values \

db2 (cont.) => ('A1', 1 ,'01'),('A1' ,1, '02'),('A1', 1, '03'), \

db2 (cont.) => ('A2', 1, '01'),('A2', 2, '01'),('A2', 2 ,'02') \

db2 (cont.) => ), \

db2 (cont.) =>  t1(t11,t22,t33,t44,t55) as ( \

db2 (cont.) =>  select t1,t2,t3,rownumber() over(partition by t1,t2),rownumber() over(partition by t1,t2) as t4 from t \

db2 (cont.) => ), \

db2 (cont.) => t3(s1,s2,s3,s4,s5) as( \

db2 (cont.) => select t11,t22,cast(t33 as varchar(100)),t44,t55 from t1 where T44 =1 and t55=1 \

db2 (cont.) =>  union all \

db2 (cont.) => select a.s1,a.s2,cast(a.s3||'-'||b.t33 as varchar(100)),a.s4+1,a.s5 from t3 a,t1 b \

db2 (cont.) =>  where a.s1=b.t11 and a.s4 = b.t55-1) \

db2 (cont.) => select s1,s2,s3 from t3 x where x.s4=(select max(s4) from t3 y where x.s1=y.s1) order by s1,s2

S1 S2          S3

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

SQL0347W  递归公共表表达式 "DB2ADMIN.T3" 可能包含无限循环。  SQLSTATE=01605

A1           1 01-02-03

A2           1 01-02

A2           2 01-02

已选择 3 条记录,打印 1 条警告消息。

ok,搞定!

个人认为db2还是很强大的!大家一起学习!

上边的代码在逻辑可以了,还需要改改

with t (t1,t2,t3) as (

values

('A1', 1 ,'01'),('A1' ,1, '02'),('A1', 1, '03'),

('A2', 1, '01'),('A2', 2, '01'),('A2', 2 ,'02')

),

t1(t11,t22,t33,t44,t55) as (

select t1,t2,t3,rownumber() over(partition by t1,t2),rownumber() over(partition by t1,t2) as t4 from t

),

t3(s1,s2,s3,s4,s5) as(

select t11,t22,cast(t33 as varchar(100)),t44,t55 from t1 where T44 =1 and t55=1

union all

select a.s1,a.s2,cast(a.s3||'-'||b.t33 as varchar(100)),a.s4+1,a.s5 from t3 a,t1 b where a.s1=b.t11 and a.s2=b.t22  and a.s4 = b.t55-1

)

select s1,s2,s3 from t3 x where x.s4=(select max(s4) from t3 y where x.s1=y.s1 and x.s2=y.s2) order by s1,s2

;

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

'A1'        1        '01-02-03'

'A2'        1        01

'A2'        2        '01-02'

这样才对!

转载于:https://www.cnblogs.com/xioxu/archive/2008/03/18/1110796.html

数据旋转及DB2递归的应用相关推荐

  1. c语言折半查找递归程序,C语言数据结构中二分查找递归非递归实现并分析

    C语言数据结构中二分查找递归非递归实现并分析 前言: 二分查找在有序数列的查找过程中算法复杂度低,并且效率很高.因此较为受我们追捧.其实二分查找算法,是一个很经典的算法.但是呢,又容易写错.因为总是考 ...

  2. db2 linux 导入数据_实现DB2数据库迁移之导入步骤在Linux下

    今天是要和大家一起讨论的是在Linux操作平台下正确实现DB2数据库迁移之导入的实际操作步骤,如果你对DB2数据库迁移之导入的实际操作步骤,心存好奇的话,以下的文章将会揭开它的神秘面纱. (1)解压 ...

  3. Qz学算法-数据结构篇(表达式、递归)

    前缀.中缀.后缀表达式->(逆波兰表达式) 1.前缀表达式(波兰表达式) 前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前 举例说明:(3+4)×5-6对应的前缀表达式就是-×+3456 ...

  4. 目标检测训练数据旋转python代码——数据增广(一)

    转载请在首行附上原文链接!有帮助的话记得点ge赞. 针对目标检测任务,对训练数据做旋转进而达到数据增广的python2代码,网上没找到,自己写了一份. 另外附上一份,检查旋转后效果的Python代码( ...

  5. db2 linux 导入数据_linux导入db2数据库

    AIX系统上实现DB2数据导入LINUX系统 下面为您介绍的DB2数据导入导出方法实现的是AIX系统上DB2数据导入LINUX系统,如果您对DB2数据导入方面感兴趣的话,不妨一看. (一)AIX系统上 ...

  6. db2删除完全相同的重复数据_[数据库]DB2删除重复数据

    [数据库]DB2删除重复数据 0 2016-05-03 12:00:03 有时候DB2建表时不设置主键,就可能存在脏数据,例如:两条一样数据重复存在,这时候就需要将重复记录删除,然后留下一条记录.CR ...

  7. db2 linux 数据导出_linux db2 导出数据库

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  8. ajax遍历递归树数据,怎么用JS递归发送AJAX请求

    解决了写一个我自己的 没有想象的那么困难是我自己想复杂了 function onNetChange() { var nt = plus.networkinfo.getCurrentType(); if ...

  9. SQL数据旋转的问题

    表A uaserid uaserid1 uaserid2 uaserid3 1 34 5 表B为空表,如何获得表A的数据插入表B,最终结果是 id 3 4 5 解决方法: if object_id(' ...

最新文章

  1. 人名翻译_考研英语翻译:句子中出现人名怎么办?
  2. PE文件和COFF文件格式分析——导出表的应用——通过导出表隐性加载DLL
  3. 最小生成树prim算法———模板
  4. 【IT资讯】编程语言面临重新洗牌,这六种要凉凉
  5. ORA-01658:无法为表空间XXX中的段创建initial区
  6. Saving Tang Monk II HihoCoder - 1828(2018北京网络赛三维标记+bfs)
  7. agx 安装ros opencv_Ubuntu下安装realsense+melodic+OpenCV
  8. linux自动更新漏洞,Linux爆本地提权漏洞 请立即更新udev程序
  9. sprintf 、vsprintf 、_vsntprintf
  10. Octave GNU默认配置文件位置
  11. SSH复用代码最终版
  12. 从软件测试转行做前端,转行软件测试或者前端开发有前途么?
  13. 生物信息学: 导论与方法 | 总结笔记
  14. 机器学习常见概率模型
  15. hadoop安装(包含hive)
  16. 从零起步做到Linux运维经理,你必须管好的23个细节
  17. 高中数学集合知识点小题解题方法
  18. Rounded Numbers
  19. WannaCrypt0r分析报告
  20. 教育培训行业现状分析

热门文章

  1. 1026 程序运行时间 (15 分
  2. 通过syslog接收远程日志
  3. mysql数据库引擎怎么看,值得收藏!
  4. 阿里P8大佬亲自教你!java程序设计第四版pdf
  5. 阿里P8亲自讲解!java实例变量和类变量
  6. Java作业09-异常
  7. shell:多个文件按行合并
  8. ES6标准入门(第二版)pdf
  9. 集算器协助Java处理结构化文本之条件过滤
  10. 有一句说一千句,是作家....