ORACLE / SQL:wm_concat&订购

时间:2011-02-11 15:00:34

标签: sql oracle oracle11g wm-concat

我正在使用oracle 11(不确定确切的版本,但由于LISTAGG不起作用,我认为它不是第2版)通过ODBC和水晶报告2008.

这是我遇到的问题:

这是一张表:

TABLE ODB.TASK_CARD_CONTROL  
------------------------------------------  
task_card     control_category     code  
------------------------------------------  
1                  zone             17  
1                  zone             33  
1                  zone             21  
2                  zone             18  
2                  zone             05  
3                  zone             55  
3                  zone             32  
3                  zone             72 

我正在使用WM_CONCAT函数来获取类似的内容:

task_card      zones
1              17,33,21
2              18,05
3              55,32,72

以下是SQL:

SELECT TASK_CARD, WM_CONCAT(code) as ZONES
FROM ODB.TASK_CARD_CONTROL
WHERE ODB.TASK_CARD_CONTROL.CONTROL_CATEGORY = 'ZONE'
GROUP BY TASK_CARD

但是我希望对区域进行排序,所以我尝试了这个:

SELECT TASK_CARD, WM_CONCAT(code) as ZONES
FROM (SELECT TASK_CARD, CODE, CONTROL_CATEGORY FROM ODB.TASK_CARD_CONTROL 
ORDER BY CODE)
WHERE ODB.TASK_CARD_CONTROL.CONTROL_CATEGORY = 'ZONE'
GROUP BY TASK_CARD

但由于某种原因,它会返回以下错误:

Failed to retrieve data from the database.
Details: 42S22:[Oracle][ODBC][Ora]ORA-00904: 
"ODB"."TASK_CARD_CONTROL"."CONTROL_CATEGORY" : invalid identifier

我真的不明白我在这里做错了什么......有人能给我一个暗示吗?

6 个答案:

答案 0 :(得分:5)

对于仍在使用wm_CONCAT(a.k.a。较旧的db版本)的任何人: 解决方案是添加不同的条件,然后它还将升序应用于连接值。

不要问为什么没有记录,但它会起作用。

此外,在子查询中使用order by,wm_concat之前只会随机化顺序,所以不应该推荐它。

请求的SQL的示例:

SELECT TASK_CARD, WM_CONCAT(distinct code) as ZONES
FROM ODB.TASK_CARD_CONTROL
WHERE ODB.TASK_CARD_CONTROL.CONTROL_CATEGORY = 'ZONE'
GROUP BY TASK_CARD;

请注意,在程序/包中使用时,distinct选项不起作用。

答案 1 :(得分:2)

您无法从内部查询外部引用ODB.TASK_CARD_CONTROL.CONTROL_CATEGORY。尝试:

SELECT TASK_CARD, WM_CONCAT(code) as ZONES
FROM (SELECT TASK_CARD, CODE, CONTROL_CATEGORY FROM ODB.TASK_CARD_CONTROL 
      WHERE ODB.TASK_CARD_CONTROL.CONTROL_CATEGORY = 'ZONE'
      ORDER BY CODE)
GROUP BY TASK_CARD

答案 2 :(得分:0)

如果您在from子句中给子查询一个名称,那么您可以引用子查询本身中的列

SELECT t1.TASK_CARD
, WM_CONCAT(t1.code) as ZONES
FROM 
(SELECT TASK_CARD, CODE, CONTROL_CATEGORY FROM ODB.TASK_CARD_CONTROL ORDER BY CODE) t1
WHERE t1.CONTROL_CATEGORY = 'ZONE'
GROUP BY t1.TASK_CARD

答案 3 :(得分:0)

  1. 按所需列排序,然后
  2. 按行号排序外部查询。
  3. 使用此功能。
  4. 此函数具有最后一个rownum顺序的逻辑:

    Select wmsys.wm_concat(t) CONCAT from 
    (
        Select t from (
            Select t from (
                Select 'aa' t from dual
                union
                Select 'zz' t from dual
                union
                Select 'pp' t from dual
                union
                Select 'll' t from dual
                union
                Select 'mm' t from dual
                union
                Select 'xx' t from dual
                union
                Select 'cc' t from dual
            ) a 
            order by t
        ) order by rownum
    ) t
    

答案 4 :(得分:0)

11g第2版中引入了

LISTAGG

因此,在Oracle版本 11g 之前,不支持LISTAGG,您可以使用 ROW_NUMBER() SYS_CONNECT_BY_PATH 功能

参见 Oracle String Aggregation Techniques

SELECT task_card,
  LTRIM(MAX(SYS_CONNECT_BY_PATH(code,','))
  KEEP (DENSE_RANK LAST ORDER BY curr),',') AS zones
  FROM   (SELECT task_card,
                code,
                ROW_NUMBER() OVER (PARTITION BY fruit ORDER BY code) AS curr,
                ROW_NUMBER() OVER (PARTITION BY fruit ORDER BY code) -1 AS prev
         FROM   table_name)
  GROUP BY task_card
  CONNECT BY prev = PRIOR curr AND task_card= PRIOR task_card
 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>

您将收到“无效标识符”错误:

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

因此,没有必要依赖未记录的功能,这在最新版本中不再可用。

答案 5 :(得分:-1)

使用ListAgg而不是wm_concat

SELECT TASK_CARD, ListAgg(code) within (order by code asc) as ZONES

http://nimishgarg.blogspot.com/2010/07/oracle-differece-between-wmconcat-and.html