假如有如下表,其中各个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. Jersey 2.x 基于 Servlet 的服务器端应用

    下面的依赖通常应用到应用服务器上(servlet 容器),同时这个应用服务器上没有整合任何 JAX-RS 的实现. 因此,这个应用服务器需要包含有 JAX-RS API 和 Jersey 实现,同时部 ...

  2. 14西安区域赛C - The Problem Needs 3D Arrays

    最大密度子图裸题,详情请见胡博涛论文: https://wenku.baidu.com/view/986baf00b52acfc789ebc9a9.html 不加当前弧优化t到死= = //#prag ...

  3. php数组转化为字符串

    1.函数explode();  这个是字符串转化为数组 , implode() ;这个是数组转化为字符串. $array=explode(separator,$string); $string=imp ...

  4. OC 类的本质和分类

    一.分类 (一)分类的基本知识  概念:Category  分类是OC特有的语言,依赖于类. 分类的作用:在不改变原来的类内容的基础上,为类增加一些方法. 添加一个分类: 文件结构图: 在分类中添加一 ...

  5. vuex2.0+两个小例子

    首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各核心概念的理解. 废话少说,直接上干货.这是官网上的一 ...

  6. 标签传播算法(Label Propagation)及Python实现

    众所周知,机器学习可以大体分为三大类:监督学习.非监督学习和半监督学习.监督学习可以认为是我们有非常多的labeled标注数据来train一个模型,期待这个模型能学习到数据的分布,以期对未来没有见到的 ...

  7. openshift rhc

    Microsoft Windows [Version 6.1.7601]Copyright (c) 2009 Microsoft Corporation. All rights reserved. C ...

  8. 0SGU 128 snake (&& ZOJ 3521) 尺取,排序二叉树,线段树 难度:2

    128. Snake time limit per test: 0.25 sec. memory limit per test: 4096 KB There are N points given by ...

  9. bzoj1081

    题解: 先暴力找规律 然后就一加一减的枚举 代码: #include<bits/stdc++.h> using namespace std; ],p[]; int main() { sca ...

  10. Hibernate基于【XML】和【注解】——完整实例

    Eclipse中新建Java Project工程: 工程结构  和  需要的Jar包: 我用的SqlServer数据库,所以连接数据库的Jar包是sqljdbc4.jar 一.基于XML配置 1.实体 ...