假如有如下表,其中各个i值对应的行数是不定的

  1. SQL> select * from t;
  2. I A          D
  3. ---------- ---------- -------------------
  4. 1 b          2008-03-27 10:55:42
  5. 1 a          2008-03-27 10:55:46
  6. 1 d          2008-03-27 10:55:30
  7. 2 z          2008-03-27 10:55:55
  8. 2 t          2008-03-27 10:55:59
  9. --- 要获得如下结果,注意字符串需要按照D列的时间排序:
  10. 1  d,b,a
  11. 2  z,t

这是一个比较典型的行列转换,有好几种实现方法

1.自定义函数实现

  1. create or replace function my_concat(n number)
  2. return varchar2
  3. is
  4. type typ_cursor is ref cursor;
  5. v_cursor typ_cursor;
  6. v_temp varchar2(10);
  7. v_result varchar2(4000):= '';
  8. v_sql varchar2(200);
  9. begin
  10. v_sql := 'select a from t where i=' || n ||' order by d';
  11. open v_cursor for v_sql;
  12. loop
  13. fetch v_cursor into v_temp;
  14. exit when v_cursor%notfound;
  15. v_result := v_result ||',' || v_temp;
  16. end loop;
  17. return substr(v_result,2);
  18. end;
  19. SQL> select i,my_concat(i) from t group by i;
  20. I MY_CONCAT(I)
  21. ---------- --------------------
  22. 1 d,b,a
  23. 2 z,t

虽然这种方式可以实现需求,但是如果表t的数据量很大,i的值又很多的情况下,因为针对每个i值都要执行一句select,扫描和排序的次数和i的值成正比,性能会非常差。

2.使用sys_connect_by_path

  1. select i,ltrim(max(sys_connect_by_path(a,',')),',') a
  2. from
  3. (
  4. select i,a,d,min(d) over(partition by i) d_min,
  5. (row_number() over(order by i,d))+(dense_rank() over (order by i)) numid
  6. from t
  7. )
  8. start with d=d_min connect by numid-1=prior numid
  9. group by i;

从执行计划上来看,这种方式只需要扫描两次表,比自定义函数的方法,效率要高很多,尤其是表中数据量较大的时候: 
 
3.使用wm_sys.wm_concat 
这个函数也可以实现类似的行列转换需求,但是似乎没有办法做到直接根据另外一列排序,所以需要先通过子查询或者临时表排好序:

  1. SQL> select i,wmsys.wm_concat(a) from t group by i;
  2. I WMSYS.WM_CONCAT(A)
  3. ---------- --------------------
  4. 1 b,a,d
  5. 2 z,t
  6. SQL> select i,wmsys.wm_concat(a)
  7. 2  from
  8. 3  (select * from t order by i,d)
  9. 4  group by i;
  10. I WMSYS.WM_CONCAT(A)
  11. ---------- --------------------
  12. 1 d,b,a
  13. 2 z,t

执行计划上看,只需要做一次表扫描就可以了,但是这个函数是加密过的,执行计划并不能显示函数内部的操作。

Oracle 多行合并一行 方法的更多相关文章

  1. oracle多行合并一行

    以上图为例 执行SQL语句: select d.group_id,to_char(wm_concat(d.tag)) from Imglib_Group_Tag d where d.group_id= ...

  2. SQL实现多行合并一行 .

    ORACLE纯SQL实现多行合并一行[转] 项目中遇到一个需求,需要将多行合并为一行.表结构如下:NAME                            Null           Type ...

  3. ORACLE纯SQL实现多行合并一行

    项目中遇到一个需求,需要将多行合并为一行.表结构如下:NAME                            Null           Type---------------------- ...

  4. JS行合并处理方法

    //行合并 function _w_table_rowspan(col){ _w_table_firsttd = ""; _w_table_currenttd = "&q ...

  5. oracle 多行合并为一行

    sys_connect_by_path select i,ltrim(max(sys_connect_by_path(a,',')),',') afrom(select i,a,d,min(d) ov ...

  6. Sql:多行合并一行以及多条数据取时间最早的那条

    有两个导数据的需求,1.一张表里面每一个订单号可能对应多条数据,每个单号返回时间最早的那条. 2.根据条件查询某个字段并按照逗号,合并在一起. 表类似结构如下: 第一条sql:select c.Id, ...

  7. oracle 多行变一行 wmsys.wm_concat

    背景        还是那个问题,部分程序员喜欢用sql解决问题.发现了这个函数,当初真是大喜过望,现在是哭笑不得.10g支持这个函数,11好像不支持了,而且只有oracle支持,其实自己写个通用方法 ...

  8. Oracle PIVOT 行转列方法

    数据库中業種的存储如下图: SELECT * FROM M_TORIHIKISAKI_GYOSYU 其中GYIUSYU_CD字段代表不同的業種 而画面需要实现下图所示样式:(将每条数据的業種横向展开显 ...

  9. Oracle 多行变一行

    https://blog.csdn.net/rainyspring4540/article/details/50231521

随机推荐

  1. 20170228VBA提取邮件部分信息

    Sub 获取OutLook收件箱主题和正文() On Error Resume Next Dim sht As Worksheet Dim olApp As Outlook.Application D ...

  2. 关于Floyd求解最小环的问题

    最近学习了floyd的奇妙用处,求解最小环,自己的领悟写在了纸上. 对于一个最小环,显然至少要包含三个点(此处不把两个点的回路称之为环) 从大体上考虑的话,一定有一个点与左右两侧的点是直接连接的(即不 ...

  3. BZOJ 1601 [Usaco2008 Oct]灌水 (最小生成树)

    题意 Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记.把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库. 建造一个水库需要 ...

  4. spring--mvc用戶注册用户名验重

    spring--mvc用戶注册用户名验重 注册是验证用户名是否重复.post方法,当表单的用户名文本框失去焦点时,由ajax方法指定,进行@RequestMapping指定的url提交时调用的方法. ...

  5. 信号处理函数的返回setjmp/longjmp

    信号处理函数可以正常返回,也可以调用其他函数返回到程序的主函数中,而不是从该处理程序返回. 正如ANSI C标准所说明的,一个信号处理程序可以返回或者调用abort.exit或longjmp(goto ...

  6. ArrayList Vector LinkedList(一)

    ArrayList Vector LinkedList 区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,都允许直接序号索引元素, ...

  7. mysql日常运维

    一.Linux内核和发行版本 uname -a cat /etc/issue  二.glibc的版本   /lib/libc.so.6    ---没有man函数据的动态链接库   三.MySQL的版 ...

  8. ZOJ 3161 Damn Couples 动态规划 难度:2

    Damn Couples Time Limit: 1 Second      Memory Limit: 32768 KB As mentioned in the problem "Coup ...

  9. 对spring 对持久层的支持和数据库连接池的理解

    1.spring对持久层的支持在于,得到数据库连接之后操作上的封装,将操作简化了.也就是说以后操作sql语句就用XXXTemplate(就是一个工具类)对象了. 2.数据库连接池的作用只在于得到数据库 ...

  10. C++primer 练习4.31-4.35

    Exercise 4.31: 编写程序从标准输入设备读入字符串,并把该串存放在字 符数组中.描述你的程序如何处理可变长的输入.提供比 你分配的数组长度长的字符串数据测试你的程序. string in_ ...