Sql listagg查询结果不同值

Sql listagg查询结果不同值,sql,oracle,Sql,Oracle,我有这样的桌子 +----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | |

我有这样的桌子

+----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | | ctx10000013 | 12474748,12474749,12474750 | +----------------------------+----------------------------+ 表的输出应该是

+----------------------------+----------------------------+ | Customer_ref(varchar2(40)) | Event_source-varchar2(40)) | +----------------------------+----------------------------+ | ctx10000012 | 12474748,1247574,1247674 | | ctx10000013 | 12474748 - 12474750 | +----------------------------+----------------------------+ 如何在不使用with as table select的单选择查询中执行此操作。因为我在游标内使用此选择查询


非常感谢您的帮助。

这里没有内置的功能来帮助您。因此,编写一个名为ranges_string或任何您喜欢的名称的PL/SQL函数,将字符串从“1,2,3,5,7,8,9”转换为“1-3,5,7-9”或您需要的任何形式,然后在select语句中调用它:

select ranges_string( listagg(event_source, ', ') within group(order by event_source) )
from
(
  select distinct customer_ref, event_source from custeventsource
  where customer_ref = acc.customer_ref and end_dtm is null
);
编辑:这里有一个转换为范围的函数,例如,将“1,2,3,6,7,8,10,12,13,14”转换为“1-3,6-8,10,12-14”。我没有花太多时间在它上面,所以它肯定不是很好,所以请随意更改它:-

create or replace function convert_ranges(vi_numbers varchar2) return varchar2 is
  type table_of_integer is table of integer index by binary_integer;
  v_numbers table_of_integer;
  v_ranges varchar2(4000);
  v_pos integer;
  v_count integer;
begin
  -- Tokenize
  select regexp_substr(vi_numbers, '[^,]+', 1, level) as num
  bulk collect into v_numbers
  from dual
  connect by regexp_substr(vi_numbers, '[^,]+', 1, level) is not null;

  -- Collect
  v_ranges := v_numbers(1);
  v_pos := 2;
  while v_pos <= v_numbers.count loop
    v_count := 0; 
    while v_pos <= v_numbers.count and v_numbers(v_pos) = v_numbers(v_pos-1) + 1 loop
      v_count := v_count + 1;
      v_pos := v_pos + 1;
    end loop;
    if v_count > 0 then
      v_ranges := v_ranges || '-' || v_numbers(v_pos-1);
    end if;
    if v_pos <= v_numbers.count then
      v_ranges := v_ranges || ',';
      v_ranges := v_ranges || v_numbers(v_pos);
      v_pos := v_pos + 1;
    end if;
  end loop;

  return v_ranges;
end convert_ranges;

不带out的单选查询使用as表select。因为我在游标内使用此select查询。这是什么意思?你能把不起作用的示例代码放进去吗?@Pratik With在single select查询中,我只想给出eventsoucre是否在序列中的输出。如果序列需要以“-”作为分隔符。请各位。。。请帮我解决这个问题..我需要你的帮助..你能帮我写ranges\u string函数吗?因为我是sql的新手。我添加了一个函数,或多或少满足了你的需要。希望这有帮助。顺便说一句:如果你发布了一个新的请求,而不是在已经解决的请求中添加评论,我相信你会得到立即的帮助。如果他们只看到你的请求,肯定有很多人会很快提供这样的功能。
create or replace function convert_ranges(vi_numbers varchar2) return varchar2 is
  type table_of_integer is table of integer index by binary_integer;
  v_numbers table_of_integer;
  v_ranges varchar2(4000);
  v_pos integer;
  v_count integer;
begin
  -- Tokenize
  select regexp_substr(vi_numbers, '[^,]+', 1, level) as num
  bulk collect into v_numbers
  from dual
  connect by regexp_substr(vi_numbers, '[^,]+', 1, level) is not null;

  -- Collect
  v_ranges := v_numbers(1);
  v_pos := 2;
  while v_pos <= v_numbers.count loop
    v_count := 0; 
    while v_pos <= v_numbers.count and v_numbers(v_pos) = v_numbers(v_pos-1) + 1 loop
      v_count := v_count + 1;
      v_pos := v_pos + 1;
    end loop;
    if v_count > 0 then
      v_ranges := v_ranges || '-' || v_numbers(v_pos-1);
    end if;
    if v_pos <= v_numbers.count then
      v_ranges := v_ranges || ',';
      v_ranges := v_ranges || v_numbers(v_pos);
      v_pos := v_pos + 1;
    end if;
  end loop;

  return v_ranges;
end convert_ranges;