Oracle 10g多列字符串连接

时间:2011-03-08 04:11:31

标签: sql oracle oracle10g

是否可以构造SQL来连接多行的列值?

以下是一个例子:

表A

PID
A
B
C

表B

PID   SEQ    Desc

A     1      Have
A     2      a nice
A     3      day.
B     1      Nice Work.
C     1      Yes
C     2      we can 
C     3      do 
C     4      this work!

SQL的输出应该是 -

PID   Desc

A     day.||a nice||Have
B     Nice Work.
C     this work!||do||we can||Yes

因此,输出表的Desc列基本上是表B中SEQ值的串联,并且值按SEQ的降序附加,并由||分隔。 ?

有关SQL的任何帮助吗?

仅供参考 - 在不使用功能或存储过程的情况下寻找解决方案

4 个答案:

答案 0 :(得分:2)

来自here

但我会随时使用某个功能。

SQL> select deptno
  2       , rtrim(ename,',') enames
  3    from ( select deptno
  4                , ename
  5                , rn
  6             from emp
  7            model
  8                  partition by (deptno)
  9                  dimension by (row_number() over
 10                                (partition by deptno order by ename) rn
 11                               )
 12                  measures     (cast(ename as varchar2(40)) ename)
 13                  rules
 14                  ( ename[any] order by rn desc = ename[cv()]||','||ename[cv()+1]
 15                  )
 16         )
 17   where rn = 1
 18   order by deptno
 19  /

    DEPTNO ENAMES
---------- ----------------------------------------
        10 CLARK,KING,MILLER
        20 ADAMS,FORD,JONES,SCOTT,SMITH
        30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD

答案 1 :(得分:1)

分层查询应该有效。需要一点额外的技巧,因为你想从每个PID的最高SEQ开始。

SELECT pid, fulldesc FROM (
  SELECT pid, SYS_CONNECT_BY_PATH( desc, '||' ) fulldesc, seq, minseq FROM (
    SELECT pid, seq, desc,
           MAX(seq) OVER (PARTITION BY pid) maxseq,
           MIN(seq) OVER (PARTITION BY pid) minseq
      FROM tableB
    )
    START WITH seq = maxseq
    CONNECT BY pid = PRIOR pid AND seq = PRIOR seq - 1
  )
  WHERE seq = minseq
  ORDER BY pid
  ;

修改:在评论中添加过滤器的一种方法:

SELECT pid, fulldesc FROM (
  SELECT pid, SYS_CONNECT_BY_PATH( desc, '||' ) fulldesc, seq, minseq FROM (
    SELECT pid, seq, desc,
           MAX(seq) OVER (PARTITION BY pid) maxseq,
           MIN(seq) OVER (PARTITION BY pid) minseq
      FROM tableB
      WHERE pid IN (SELECT pid FROM tableB WHERE desc='day.')
    )
    START WITH seq = maxseq
    CONNECT BY pid = PRIOR pid AND seq = PRIOR seq - 1
  )
  WHERE seq = minseq
  ORDER BY pid

答案 2 :(得分:1)

以下是很多关于如何做到的例子(其中一些已经提到),包括类似于listagg()的完整实现:​​

http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php#user_defined_aggregate_function

答案 3 :(得分:0)

你想在Oracle中做一些GROUP_CONCAT在MySQL中做什么吗?

如果存在,您可以使用WM_CONCAThttp://www.oracle-base.com/articles/misc/string-aggregation-techniques.php#wm_concat 但它没有证件,所以如果我是你,我就不会在生产中使用它。

不幸的是,在10g上还没有LISTAGG

对于10g的生产环境,我会选择Dave Costa的答案。