如何使用带有多个值的Oracle LISTAGG函数?

时间:2018-08-28 11:40:40

标签: oracle select listagg

我有一个如下所示的“ ITEMS”表:

ITEM_NO     ITEM_NAME   
1               Book   
2               Pen   
3               Sticky Notes   
4               Ink   
5               Corrector   
6               Ruler  

在另一个“ EMP_ITEMS”表中,我具有以下内容:

EMPLOYEE        ITEMS_LIST   
 John           1,2   
 Mikel          5   
 Sophia         2,3,6  
 William        3,4   
 Daniel         null   
 Michael        6  

输出必须是这样的:

EMPLOYEE        ITEMS_LIST      ITEM_NAME   
John            1,2             Book,Pen   
Mikel           5               Corrector   
Sophia          2,3,6           Pen,Sticky Notes,Ruler   
William         3,4             Sticky Notes,Ink   
Daniel          null            null   
Michael         6               Ruler

我使用以下查询:

SELECT e.EMPLOYEE,e.ITEMS_LIST, LISTAGG(i.ITEM_NAME, ',') WITHIN GROUP (ORDER BY i.ITEM_NAME) ITEM_DESC 
 FROM EMP_ITEMS e  
INNER JOIN ITEMS i ON i.ITEM_NO = e.ITEMS_LIST 
GROUP BY e.EMPLOYEE,e.ITEMS_LIST;

但是有一个错误:

  

ORA-01722:无效的数字

1 个答案:

答案 0 :(得分:4)

  

但是有一个错误:ORA-01722: invalid number

这是因为您的ITEMS_LIST是由数字和逗号组成的字符串,实际上不是数字列表,并且您正在尝试将单个项目编号与项目列表进行比较。

而是将其视为字符串,以查找子字符串匹配项。为此,您需要将定界符中的字符串括起来,并进行比较以查看一个字符串是否是另一个字符串的子字符串:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE Items ( ITEM_NO, ITEM_NAME ) As
SELECT 1, 'Book' FROM DUAL UNION ALL
SELECT 2, 'Pen' FROM DUAL UNION ALL
SELECT 3, 'Sticky Notes' FROM DUAL UNION ALL
SELECT 4, 'Ink' FROM DUAL UNION ALL
SELECT 5, 'Corrector' FROM DUAL UNION ALL
SELECT 6, 'Ruler' FROM DUAL;

CREATE TABLE emp_items ( EMPLOYEE, ITEMS_LIST ) AS
SELECT 'John', '1,2' FROM DUAL UNION ALL
SELECT 'Mikel', '5' FROM DUAL UNION ALL
SELECT 'Sophia', '3,2,6' FROM DUAL UNION ALL
SELECT 'William', '3,4' FROM DUAL UNION ALL
SELECT 'Daniel', null FROM DUAL UNION ALL
SELECT 'Michael', '6' FROM DUAL;

查询1

SELECT e.employee,
       e.items_list,
       LISTAGG( i.item_name, ',' )
         WITHIN GROUP (
           ORDER BY INSTR( ','||e.items_list||',', ','||i.item_no||',' )
         ) AS item_names
FROM   emp_items e
       LEFT OUTER JOIN
       items i
       ON ( ','||e.items_list||',' LIKE '%,'||i.item_no||',%' )
GROUP BY e.employee, e.items_list

Results

| EMPLOYEE | ITEMS_LIST |             ITEM_NAMES |
|----------|------------|------------------------|
|     John |        1,2 |               Book,Pen |
|    Mikel |          5 |              Corrector |
|   Daniel |     (null) |                 (null) |
|   Sophia |      3,2,6 | Sticky Notes,Pen,Ruler |
|  Michael |          6 |                  Ruler |
|  William |        3,4 |       Sticky Notes,Ink |