listunagg函数?

问题描述 投票:6回答:3

像listunagg函数那样在oracle中有这样的东西吗?例如,如果我有这样的数据:

------------------------------------------------------------
| user_id | degree_fi    | degree_en       | degree_sv       |
--------------------------------------------------------------
| 3601464 | 3700         |  1600           |  2200           |
|  1020   | 100          |  0              |   0             |
| 3600520 | 100,3200,400 | 1300, 800, 3000 | 1400, 600, 1500 |
| 3600882 |  0           |   100           |  200            |
--------------------------------------------------------------

我想显示这样的数据:

-----------------------------------------------
| user_id | degree_fi | degree_en | degree_sv |
-----------------------------------------------
| 3601464 | 3700      |  1600     |  2200     |
|  1020   | 100       |  0        |   0       |
| 3600520 |  100      | 1300      |  1400     |
| 3600882 |  0        |   100     |  200      |
| 3600520 |  3200     |   800     |  600      |
| 3600520 |  400      | 3000      |  1500     |
-----------------------------------------------

我试图找到一些像listagg相反的功能,却找不到任何功能。提前致谢 :-)

string oracle csv oracle11g tokenize
3个回答
7
投票

正如@be现在已经在评论中指出Oracle没有提供这样的功能。因此,作为快速解决方法,您可以编写类似的查询:

with t1(user_id, degree_fi, degree_en, degree_sv) as
(
  select 3601464, '3700', '1600', '2200' from dual union all
  select 1020   , '100' , '0'   , '0'    from dual union all
  select 3600520, '100,3200,400', '1300, 800, 3000', '1400, 600, 1500'  from dual union all
  select 3600882, '0',    '100',  '200'  from dual
),
Occurence(ocr) as(
  select Level as ocr
    from (select max(greatest(regexp_count(degree_fi, '[^,]+')
                             , regexp_count(degree_en, '[^,]+')
                             , regexp_count(degree_sv, '[^,]+')
                             )
                    ) mx
            from t1    
          ) 
    connect by level <= mx
)
select *
  from (
select User_id
     , regexp_substr(degree_fi, '[^,]+', 1, o.ocr) as degree_fi
     , regexp_substr(degree_en, '[^,]+', 1, o.ocr) as degree_en
     , regexp_substr(degree_sv, '[^,]+', 1, o.ocr) as degree_sv
   from t1 t
  cross join Occurence o
)
where degree_fi is not null
  or degree_en is not null 
  or degree_sv is not null

结果:

User_Id   Degree_Fi  Degree_En  Degree_Sv
------------------------------------------------------------ 
3601464   3700       1600       2200 
1020      100        0          0 
3600520   100        1300       1400 
3600882   0          100        200 
3600520   3200       800        600 
3600520   400        3000       1500 

0
投票

listunagg function套装提供OraOpenSource Utils。它也很好用。


-1
投票

要想清楚一个列表,请考虑Tom在Oracle的“Ask Tom”中所说的内容,请参阅http://www.oracle.com/technetwork/issue-archive/2007/07-mar/o27asktom-084983.html代码清单3或4。

Tom不讨论的首选选项适用于短字符串(<34个字符)。我使用Oracle DBMS_UTILITY.comma_to_table函数。例:

SET SERVEROUTPUT ON
DECLARE
/** test data **/   
  L_LIST1   VARCHAR2(500) := '"A","B","C","Pierre - Andre","D","E","OFVampFVapos;CBryan","F","G","H","I","J"';
  l_list2   VARCHAR2(500);
  l_tablen  BINARY_INTEGER;
  l_tab     DBMS_UTILITY.uncl_array;
BEGIN
  DBMS_OUTPUT.put_line('l_list1 : ' || l_list1);

  DBMS_UTILITY.comma_to_table (
     list   => l_list1,
     tablen => l_tablen,
     tab    => l_tab);

  FOR i IN 1 .. l_tablen LOOP
    DBMS_OUTPUT.put_line(i || ' : ' || l_tab(i));
  END LOOP;

  DBMS_UTILITY.table_to_comma (
     tab    => l_tab,
     tablen => l_tablen,
     list   => l_list2);

  DBMS_OUTPUT.put_line('l_list2 : ' || l_list2);
end;
© www.soinside.com 2019 - 2024. All rights reserved.