【问题标题】:Concatenate Over Oracle通过 Oracle 连接
【发布时间】:2015-09-02 15:02:11
【问题描述】:

这是一个示例表数据

Fruit   Number
Apple    1
Apple    2
Apple    3
Kiwi     6
Kiwi     10

我尝试连接表格列值以获得以下内容

Fruit   Number
Apple    1-2-3
Kiwi     6-10

有没有办法查询这个或存储过程? 像 Concatenate over(partition by) 之类的东西,我对存储过程不太了解。谢谢!

【问题讨论】:

  • 您的 Oracle 数据库版本是多少? LISTAGG 从 11g 开始提供。否则,请在 Google 上搜索 Oracle 中的字符串聚合技术
  • 感谢版本是 10g,所以我不能真正使用 Listagg。还有其他方法吗?
  • 你不能在 10g 上使用 LISTAGG,因为它是在 11gR2 中引入的。
  • @SailorMoon 为 oracle 10g 添加了解决方案,请参阅更新的答案

标签: sql oracle oracle10g string-aggregation


【解决方案1】:

您不需要为此使用存储过程。使用listagg函数:

select fruit, listagg(number, ',') within group (order by number)
from mytable
group by fruit

如果你的数据库版本是 10g 还是很简单的:使用WM_CONCAT(如果不认识名字可能试试WMSYS.WM_CONCAT)函数,见this答案中的例子。万一您需要使用不同于, 的分隔符,您可以将结果包装在replace 函数中;如果您想对结果进行排序,只需在子查询中进行预排序,例如:

select fruit, replace(wm_concat(number), ',', '-')
from (select fruit, number
      from mytable
      order by number)
group by fruit

如果您出于某种神秘原因在您的实例中没有该功能,您可以使用 polyfill,请参阅我的回答 here

【讨论】:

  • 不幸的是,OP 在10g 上,不支持LISTAGG,因为它是在11gR2 中引入的。 10g 中的另一种解决方案是 ROW_NUMBER()SYS_CONNECT_BY_PATH 函数。
  • @LalitKumarB 这也可以通过wm_concat 函数实现,而无需进行不必要的递归查询。参见例如这个答案stackoverflow.com/a/4970624/1990451
  • 永远不要使用 WM_CONCAT,因为它是一个未记录的特性,并且在 Oracle 12c 中被完全删除。不要仅仅依靠别人的答案,而是请花一些时间来学习和理解事实。见Why not use WM_CONCAT function in Oracle?
  • @LalitKumarB 它在 10-11 版本中工作的事实仍然意味着它可以工作并且它可以成为一个解决方案。如果您仔细阅读,这里还提供了一种如何制作自定义分析函数wm_concat 的方法,这对于 12c 来说是可以接受的。所以我依靠事实我的答案,我真的花了很多时间来学习和理解事实,尽管像你这样的人甚至不能读到最后的帖子开始评论
  • 它在 10-11 版本中工作的事实仍然意味着它工作 - 没有必要再向你解释。如果您提倡使用未记录的功能,那么您只能靠自己了。
【解决方案2】:

OP 在 Oracle 10g 上,LISTAGG 是在 11g 第 2 版 中引入的。

因此,在不支持LISTAGG11g 之前的Oracle 版本 中,您可以使用ROW_NUMBER()SYS_CONNECT_BY_PATH 函数。

SELECT fruit,
  LTRIM(MAX(SYS_CONNECT_BY_PATH(number,','))
  KEEP (DENSE_RANK LAST ORDER BY curr),',') AS fruits_agg
  FROM   (SELECT fruit,
                number,
                ROW_NUMBER() OVER (PARTITION BY fruit ORDER BY number) AS curr,
                ROW_NUMBER() OVER (PARTITION BY fruit ORDER BY number) -1 AS prev
         FROM   table_name)
  GROUP BY fruit
  CONNECT BY prev = PRIOR curr AND fruit = PRIOR fruit
 START WITH curr = 1;

注意

永远不要使用WM_CONCAT,因为它是一个未记录的功能,并且已从 12c 版本中删除。

任何一直依赖wm_concat 功能的应用程序一旦升级到12c 将无法运行。从那以后,它已被删除。见Why not use WM_CONCAT function in Oracle?

SQL> select banner from v$version where rownum = 1;

BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production

SQL> SELECT object_name
  2  FROM dba_objects
  3  WHERE owner='WMSYS'
  4  AND object_name LIKE 'WM\_%' ESCAPE '\';

OBJECT_NAME
----------------------------------------------------------------------------
WM_REPLICATION_INFO
WM_RDIFF
WM_PERIOD
WM_PERIOD
WM_OVERLAPS
WM_MEETS
WM_LESSTHAN
WM_LDIFF
WM_INTERSECTION
WM_INSTALLATION
WM_GREATERTHAN
WM_EVENTS_INFO
WM_ERROR
WM_ERROR
WM_EQUALS
WM_DDL_UTIL
WM_DDL_UTIL
WM_CONTAINS
WM_COMPRESS_BATCH_SIZES
WM_COMPRESSIBLE_TABLES

20 rows selected.

SQL>

您将收到“invalid identifier”错误:

SQL> SELECT banner FROM v$version;

BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE    12.1.0.1.0      Production
TNS for 64-bit Windows: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production

SQL> SELECT deptno, wm_concat(ename) FROM emp;
SELECT deptno, wm_concat(ename) FROM emp
               *
ERROR at line 1:
ORA-00904: "WM_CONCAT": invalid identifier

因此,没有必要依赖最新版本中不再提供的未记录的功能

【讨论】:

  • 永远不要使用 WM_CONCAT - 为什么不呢?你可以随时在 12c 中添加它,如果你看一下,例如here(顺便说一句,我的回答也指出了这一点)。
  • @smnbbrv 也许您不关心您的数据库和 Oracle 支持的需要。当说某项功能没有记录时,这意味着如果出现问题,那么您就只能靠自己了。您如何在生产环境中处理这些事情?还是你根本不在乎?
  • 当你遇到问题时,你首先来到 StackOverflow,你并不孤单。我的实时系统已启动并一直在运行,说起来很有趣,但 Oracle 支持从来没有帮助过我,可能是因为它们只是像你一样炫耀。你相信你是对的,但事实上我的回答被 5 个人接受,而你的回答只有一个人接受,这说明这可能不是真的。你在这里的行为让我再想一想,我才会介意再次去 Oracle 支持
  • @smnbbrv 每个使用 Oracle 数据库的行业都购买许可证并支付支持费用。我还没有看到没有许可证和支持的单一生产系统运行。是的,当您提到 LISTAGG 这很好时,我可以很好地看到人们对您的回答投了赞成票,我也通过投票表示赞赏。但是建议 wm_concat 不好,我只是解释了为什么,因为它不是行业标准。想象一下有人从 10g 升级到 11g 并发现该功能不可用。
  • 您会争辩说您将编写一个用户定义的函数。但为什么?内置函数比用户定义函数更快。您必须重写代码才能使用新的 LISTAGG。字符串聚合有多个选项,其中工作空间管理器中提供的 wm_concat 不被 Oracle 推荐。您可以继续争论在 PL/SQL 中做事,当然,您可以通过编程来做任何事情。但是,如果你可以在纯 SQL 中完成,则无需使用 PL/SQL。
猜你喜欢
  • 1970-01-01
  • 2021-07-15
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
  • 2019-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多