ORACLE / SQL: wm_concat & упорядочить по - PullRequest
3 голосов
/ 11 февраля 2011

Я использую oracle 11 (не уверен насчет точной версии, но поскольку LISTAGG не работает, я полагаю, это не выпуск 2) через ODBC и Crystal Reports 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 ]

5 голосов
/ 21 октября 2014

Для тех, кто все еще использует wm_CONCAT (он же более старые версии БД): решение состоит в том, чтобы добавить отдельное условие, затем он также применяет возрастающий порядок к объединенным значениям.

Не спрашивайте, почему это не такзадокументировано, но это будет работать.

Кроме того, использование порядка в подзапросе, предшествующем 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;

Просто предупреждаем, что отдельный параметр не работает при использовании в процедурах / пакетах.

2 голосов
/ 11 февраля 2011

Нельзя ссылаться на 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
0 голосов
/ 11 сентября 2015

LISTAGG был представлен в 11g Release 2 .

Поэтому в версии Oracle до 11g , где LISTAGG не поддерживается, вы можете использовать функции ROW_NUMBER () и SYS_CONNECT_BY_PATH .

См. Методы агрегации строк в Oracle

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. С тех пор он был удален. См. Почему бы не использовать функцию WM_CONCAT в 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

Следовательно, нет смысла полагаться на недокументированную функцию , которая больше не доступна в последних версиях.

0 голосов
/ 26 августа 2015
  1. Порядок по нужному столбцу, затем
  2. Порядок во внешнем запросе по номеру строки.
  3. Используйте функцию.

Эта функция имеет логику для последнего порядка 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
0 голосов
/ 28 мая 2012

Если вы дадите подзапросу в предложении 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
0 голосов
/ 16 марта 2012

Использовать 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...