Oracle 10g 多列字符串连接

发布于 2024-10-20 13:09:55 字数 527 浏览 2 评论 0原文

是否可以构造 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 方面的帮助吗?

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

Would it be possible to construct SQL to concatenate column values from multiple rows?

The following is an example:

Table A

PID
A
B
C

Table 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!

Output of the SQL should be -

PID   Desc

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

So basically the Desc column for output table is a concatenation of the SEQ values from Table B and the values are appended in the descending order of the SEQ and delimited by || ?

Any help with the SQL?

FYI - Looking for solution without using functions or stored procedures

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

深空失忆 2024-10-27 13:09:55

来自这里

但我会去任何一天都有一个功能。

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

From here

But I'd go with a function any day.

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
默嘫て 2024-10-27 13:09:55

分层查询应该可以工作。因为您想从每个 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

A hierarchical query should work. A little extra trickery is needed since you want to start with the highest SEQ for each 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
    )
    START WITH seq = maxseq
    CONNECT BY pid = PRIOR pid AND seq = PRIOR seq - 1
  )
  WHERE seq = minseq
  ORDER BY pid
  ;

Edit: One way to add a filter as requested in comment:

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
扶醉桌前 2024-10-27 13:09:55

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

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

Here are a lot of examples on how to do it (some of them have been mentioned already) including a complete implementation of something similar to listagg():

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

无人问我粥可暖 2024-10-27 13:09:55

您想在 Oracle 中执行 GROUP_CONCAT 在 MySQL 中执行的操作吗?

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

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

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

You want to do something in Oracle what GROUP_CONCAT does in MySQL?

You can use WM_CONCAT if it is present:
http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php#wm_concat
But it is undocumented, so I wouldn't use that on production, if I were you.

On 10g there is no LISTAGG yet, unfortunately.

For production environments on 10g, I would go with Dave Costa's answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文