在一个字段中组合分组值的简单方法是什么?

时间:2009-02-26 07:51:11

标签: sql oracle plsql

我的意思是:

Table PHONE_CODES:

ID CODE_NAME PHONE_CODE 
1   USA         8101
2   USA         8102
3   PERU        8103
4   PERU_MOB    81031
5   PERU_MOB    81032

我希望通过select得到这样的东西:

CODE_NAME   ZONE_CODES
USA          8101; 8102;
PERU         8103
PERU_MOB     81031; 81032;

我可以通过下面的函数得到它,但也许有更好的方法:

select distinct(CODE_NAME) as CODE_NAME, get_code_names_by_ZONE(CODE_NAME) as ZONE_CODES from PHONE_CODES;

功能:

create or replace function get_code_names_by_ZONE
(
    ZONE_CODE_NAME in varchar2
)
return varchar2
as
    codes_list varchar2(4000);
    cursor cur_codes_list is
        select p.PHONE_CODE
        from PHONE_CODES p
        where p.CODE_NAME = ZONE_CODE_NAME;
begin

    for codes_list_rec in cur_codes_list
    LOOP
        -- dbms_output.put_line('PHONE_CODE:[' || codes_list_rec.PHONE_CODE || ']');
        codes_list := codes_list || codes_list_rec.PHONE_CODE || '; ';
    end loop;

    return codes_list;

    EXCEPTION 
        when NO_DATA_FOUND then
            return 'notfound';
        WHEN others then
            dbms_output.put_line('Error code:' || SQLCODE || ' msg:' || SQLERRM);
            return null;
end get_code_names_by_ZONE;
/

4 个答案:

答案 0 :(得分:1)

一个功能将是我实现你想要的东西的首选方法。

答案 1 :(得分:1)

Tim Hall对Oracle提供的各种string aggregation techniques进行了很好的讨论。

答案 2 :(得分:0)

如果您使用的是11g,请查看SQL的新PIVOT扩展 - 最佳文档可以在“数据仓库指南”部分中找到。但我相信“... for in ...”子句的目标不能是子查询,而必须是硬编码的值列表。

答案 3 :(得分:0)

良好的链接贾斯汀。蒂姆大厅太棒了。我听从他的建议,现在是:

  1  SELECT CODE_NAME,
  2     LTRIM(MAX(SYS_CONNECT_BY_PATH(PHONE_CODES,';'))
  3     KEEP (DENSE_RANK LAST ORDER BY curr),';') AS PHONE_CODES
  4  FROM   (SELECT CODE_NAME,
  5         PHONE_CODES,
  6         ROW_NUMBER() OVER (PARTITION BY CODE_NAME ORDER BY PHONE_CODES) AS curr,
  7         ROW_NUMBER() OVER (PARTITION BY CODE_NAME ORDER BY PHONE_CODES) -1 AS prev
  8      FROM   a)
  9  GROUP BY CODE_NAME
 10  CONNECT BY prev = PRIOR curr AND CODE_NAME = PRIOR CODE_NAME
 11* START WITH curr = 1
SQL> /

CODE_NAME  PHONE_CODES
---------- --------------------------------------------------
PERU       8103
PERU_MOB   81031;81032
USA    8101;8102

dbBradley - 我不认为Pivot扩展在这里工作。 Pivot扩展需要使用聚合(sum,count,...)。