【问题标题】:Is there another command for wm_concat in oracle 9i?oracle 9i 中是否有另一个用于 wm_concat 的命令?
【发布时间】:2013-03-15 05:58:12
【问题描述】:

我有一个包含部门 ID、员工姓名和加入日期的表格。我想获取在给定日期在给定部门加入的所有员工的列表。

wm_concat 不工作。

【问题讨论】:

标签: sql oracle oracle9i


【解决方案1】:

根据this,不支持WM_CONCAT

WM_CONCAT 是一个未记录的函数,因此不受 面向用户应用程序的 Oracle

您可以使用该链接中描述的用户定义聚合函数。

【讨论】:

    【解决方案2】:

    试试wmsys.wm_concat (10g+) 或 listagg (11g+)

    【讨论】:

    • 我有 Oracle 9i。您能为此提出一些建议吗?
    【解决方案3】:

    查看String Aggregation Techniques 页面。

    对于 9i,您可以在引用的页面中声明 UDAG 函数:

    CREATE OR REPLACE TYPE t_string_agg AS OBJECT
    (
      g_string  VARCHAR2(32767),
    
      STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
        RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                           value  IN      VARCHAR2 )
         RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                             returnValue  OUT  VARCHAR2,
                                             flags        IN   NUMBER)
        RETURN NUMBER,
    
      MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                         ctx2  IN      t_string_agg)
        RETURN NUMBER
    );
    /
    
    
    
    CREATE OR REPLACE TYPE BODY t_string_agg IS
      STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
        RETURN NUMBER IS
      BEGIN
        sctx := t_string_agg(NULL);
        RETURN ODCIConst.Success;
      END;
    
      MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                           value  IN      VARCHAR2 )
        RETURN NUMBER IS
      BEGIN
        SELF.g_string := self.g_string || ',' || value;
        RETURN ODCIConst.Success;
      END;
    
      MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                             returnValue  OUT  VARCHAR2,
                                             flags        IN   NUMBER)
        RETURN NUMBER IS
      BEGIN
        returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
        RETURN ODCIConst.Success;
      END;
    
      MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                         ctx2  IN      t_string_agg)
        RETURN NUMBER IS
      BEGIN
        SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
        RETURN ODCIConst.Success;
      END;
    END;
    /
    
    
    
    CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)
    RETURN VARCHAR2
    PARALLEL_ENABLE AGGREGATE USING t_string_agg;
    /
    

    使用它就像:

    SELECT deptno, string_agg(ename) AS employees
    FROM   emp
    GROUP BY deptno;
    

    你也可以试试this question的方法(如果你有大桌子的话会很慢)

    【讨论】:

      【解决方案4】:

      试试sys.STRAGG

      SELECT department_id, 
             hire_date, 
             TRIM(TRAILING ',' FROM sys.STRAGG(last_name || ',')) names
      FROM employees
      GROUP BY department_id, hire_date
      

      SQLFiddle

      【讨论】:

      • 这是对结果的修剪,在某些情况下这是不可接受的
      【解决方案5】:

      看这里:http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php

      在该页面上查找 Oracle 9i 中 ROW_NUMBER() 和 SYS_CONNECT_BY_PATH 函数的示例。

      如果 PL/SQL 是一个选项,那么 TABLE_TO_COMMA 过程可能会起作用:http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_util.htm#ARPLS73271

      【讨论】:

        【解决方案6】:

        首先,不要使用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.
        

        您将收到“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
        

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

        有各种string aggregation techniques

        • LISTAGG 在 11gR2 及更高版本中

        例如,

        SELECT deptno, LISTAGG(ename, ',') WITHIN GROUP (ORDER BY ename) AS employees
        FROM   emp
        GROUP BY deptno;
        
            DEPTNO EMPLOYEES
        ---------- --------------------------------------------------
                10 CLARK,KING,MILLER
                20 ADAMS,FORD,JONES,SCOTT,SMITH
                30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
        
        3 rows selected.
        
        • ROW_NUMBER()SYS_CONNECT_BY_PATH 函数在 9i 及更高版本中

        例如,

        SELECT deptno,
               LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))
               KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees
        FROM   (SELECT deptno,
                       ename,
                       ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,
                       ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev
                FROM   emp)
        GROUP BY deptno
        CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno
        START WITH curr = 1;
        
            DEPTNO EMPLOYEES
        ---------- --------------------------------------------------
                10 CLARK,KING,MILLER
                20 ADAMS,FORD,JONES,SCOTT,SMITH
                30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
        
        3 rows selected.
        
        • AskTom 中描述的用户定义聚合函数 STRAGG
        • COLLECT 10g 及以上功能

        Tim Hall here 的几个很好的例子。

        【讨论】:

          猜你喜欢
          • 2012-08-20
          • 2011-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-13
          • 1970-01-01
          相关资源
          最近更新 更多