【问题标题】:Oracle 10g multiple column string concatenationOracle 10g 多列字符串连接
【发布时间】:2013-07-24 16:37:13
【问题描述】:

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

以下是一个例子:

表 A

PID 一个 乙 C

表 B

PID 序列描述 A 1 有 一个 2 一个不错 3天。 B 1 干得好。 C 1 是 C 2 我们可以 C 3 做 C 4 这个工作!

SQL 的输出应该是 -

PID 描述 一天。||美好的||有 B 干得好。 C 这工作!||做||我们可以||是

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

对 SQL 有帮助吗?

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

【问题讨论】:

标签: sql oracle oracle10g


【解决方案1】:

来自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

【讨论】:

  • 抛出 ORA-00900: 关键字 [any] 上的 SQL 语句无效!!
【解决方案2】:

分层查询应该可以工作。需要一些额外的技巧,因为您希望从每个 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

【讨论】:

  • 给出 - ORA-00904: "desc": 无效标识符
  • 抱歉,忘记在最里面的查询中包含desc。固定。
  • 我可以再问一个问题[想要添加过滤器] - 我只想包含那些 pid 的任何包含 desc 的 seq 列作为“day”。只要。在哪里添加 where 子句?
  • 一种方法是添加带有子查询的 WHERE 子句,如我编辑的答案所示。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    您想在 Oracle 中做一些 GROUP_CONCAT 在 MySQL 中所做的事情吗?

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-15
      • 2013-06-23
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多